Законность и мораль, если разные сферы «новое» и «исключить» - PullRequest
0 голосов
/ 24 января 2012

Я создаю динамический массив внутри функции. Код (размещен ниже) работает без проблем. Я задаюсь вопросом, является ли способ, который я написал, правильным способом сделать это, или это создаст проблемы в более сложных кодах в будущем. Я знаю, что конкретная задача, которую пытается выполнить моя программа (ниже), лучше достигается с помощью строк или векторов. Но я создал этот искусственный пример, чтобы объяснить мой вопрос. однако, если вы твердо уверены, что динамических массивов следует избегать, пожалуйста, не стесняйтесь делиться своим мнением и обоснованием этого.

Результат моего предыдущего исследования: я не смог найти последовательного обсуждения законности и морали создания динамических массивов с использованием new [] и последующего удаления их в другом объеме.

Спасибо за ваши мысли и идеи.

Мой пример кода следующий:

==========================

#include<iostream>
#include<string>
#include<cctype>
using namespace std;

void getNonPunct(string _str, char* &_npcarr, int &_npsize);

int main()
{
    string input_string;    
    char* npchar_arr;
    int npsize;

    cout << "Enter any string: ";
    getline(cin, input_string);

    getNonPunct(input_string, npchar_arr, npsize);    

    // Now display non-punctuation characters in the string
    cout << "string with non-punctuation characters removed:\n";

    for (int n = 0; n <= npsize - 1; n++)
        cout << npchar_arr[n];
    cout << "\n(" << npsize << ") non-punctuation characters\n";    

    // Now return the memory allocated with 'new' to heap

    delete [] npchar_arr;
    // Is it okay to 'delete' npchar_arr eve if it was created in the function
    // getNonPunct() ?

    return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void getNonPunct(string _str, char* &_npcarr, int &_npsize)    
//This void function takes an input array of strings containing arbitrary
//characters and returns a pointer to an array of characters containing only
//the non-punctuation characters in the input string. The number of
//non-punctuation characters are stored in size. Prior to the function call,
//int_arr and size are undefined. After the function call, char_arr points to
//the first location of an array of the non-punctuation character array.
//'size' is equal to the number of non-punctuation characters in the input
//string. 
{

    // First get the number of non-punctuation characters in the string

    int str_len, npcount = 0;

    str_len = static_cast<int>( _str.length() );

    _npsize = 0;
    for (int i = 0; i <= str_len - 1; i++)
    {
        if ( !ispunct(_str[i]) )
            _npsize++;        
    }

    // Now that you know how many non-punctuation characters are in the string,
    // create a (dynamic) character array of _npsize.

    _npcarr = new char [_npsize];


    for (int k = 0; k <= str_len - 1; k++)
    {
        if ( !ispunct(_str[k]) )
            _npcarr[npcount++] = _str[k];
    }    

    return;
}

Ответы [ 3 ]

4 голосов
/ 24 января 2012

Это действительно ? Да. Массив, на который указывает npchar_arr, существует до тех пор, пока вы его не уничтожите, и можно уничтожить его, используя выражение delete[] в другой функции.

Это хорошая идея ? Нет. Вам было бы намного лучше использовать интеллектуальный указатель, который автоматически управляет временем жизни объекта, освобождая вас от ответственности за delete[] ручное указание вручную.

Подумайте об использовании std::unique_ptr<char[]>, если ваш компилятор и Стандартная библиотека поддерживают unique_ptr, или std::auto_ptr или std::shared_ptr, если вы не можете использовать unique_ptr (shared_ptr также можно найти в Boost и C ++ TR1).

2 голосов
/ 24 января 2012

Выделение в одной области и удаление в другой является одной из основных причин использования динамического выделения вместо автоматической локальной переменной.

Как говорит Джеймс, предпочитайте использовать умные указатели для отслеживания динамически размещаемых объектов.

Единственное ограничение, которое я могу придумать для выделения в одной области и освобождения в другой, - это многокомпонентные приложения, в которых разные компоненты создаются с разными компиляторами (или, возможно, разными версиями одного и того же компилятора). В Windows каждый компилятор предоставляет свою собственную библиотеку управления памятью, и вы не должны освобождать память из компонента, отличного от того, который ее выделил. Или вы можете использовать предоставляемые Windows процедуры управления памятью, которые являются общими для всех компиляторов (например, HeapAlloc / HeapFree). В Linux каждый использует glibc malloc, free, new[] и delete[], так что это не такая проблема. Для других ОС вам нужно исследовать.

0 голосов
/ 24 января 2012

Этот пример очень тривиален, но представьте следующую модификацию вашего кода:

int main()
{
    string input_string;    
    char* npchar_arr;
    int npsize;

    cout << "Enter any string: ";
    getline(cin, input_string);

    getNonPunct(input_string, npchar_arr, npsize);    

    // Now display non-punctuation characters in the string
    cout << "string with non-punctuation characters removed:\n";

    for (int n = 0; n <= npsize - 1; n++)
        cout << npchar_arr[n];
    cout << "\n(" << npsize << ") non-punctuation characters\n";    

    return(0); // WHOOPS! I JUST RETURNED AND DIDN'T FREE THE MEMORY

    delete [] npchar_arr;
    // Is it okay to 'delete' npchar_arr eve if it was created in the function
    // getNonPunct() ?

    return(0);

}

Я только что вернулся, прежде чем освободить память, что приводит к утечке памяти!Конечно, вы можете подумать, что никогда не сделаете ничего подобного, но представьте себе гораздо более сложную программу, легко сделать такую ​​ошибку, как указано выше, и использование умных указателей, как показывают другие ответы, облегчит вамбеспокоиться о таких задачах.

...