Лучший вариант получения выходного динамически размещенного массива из функции? - PullRequest
2 голосов
/ 05 апреля 2010

Вот два варианта. Во-первых:

int n = 42;

int* some_function(int* input)
{
    int* result = new int[n];
    // some code
    return result;
}

int main()
{
    int* input = new int[n];
    int* output = some_function(input);

    delete[] input;
    delete[] output;
    return 0;
}

Здесь функция возвращает память, выделенную внутри функции.

Второй вариант:

int n = 42;

void some_function(int* input, int* output)
{
    // some code
}

int main()
{
    int* input = new int[n];
    int* output = new int[n];
    some_function(input, output);

    delete[] input;
    delete[] output;
    return 0;
}

Здесь память выделяется вне функции.

Теперь я использую первый вариант. Но я знаю, что многие встроенные функции c ++ используют второй вариант. Первый вариант более удобный (на мой взгляд). Но у второго также есть некоторые преимущества (вы выделяете и удаляете память в одном блоке).

Может быть, это глупый вопрос, но какой вариант лучше и почему?

Ответы [ 5 ]

6 голосов
/ 05 апреля 2010

Третий вариант

const int n = 42; 

template<class It1, class It2>
void some_function(It1 First, It1 Last, It2 output) 
{ 
    // some code 
} 

void main() 
{ 
    std::vector<int> input(n);
    std::vector<int> output(n);
    some_function(input.begin(), input.end(), output.begin()); 

} 
3 голосов
/ 05 апреля 2010

Ни один из вариантов не является предпочтительным стилем C ++, , особенно при наличии исключений. Если где-то выдается исключение (либо при выделении output, либо в теле some_function), то один или оба ваших динамически распределяемых массива вызовут утечку памяти. Предпочтительным способом является использование концепции «Распределение ресурсов при инициализации» (RAII). Безопасный код C ++ использует объекты для получения ресурсов. Их деструкторы освобождают эти ресурсы. Поскольку стек раскручивается из исключения, все ресурсы, полученные к этому моменту, благополучно освобождаются.

В случае динамически размещаемых массивов это означает std::vector. Если это не окажет негативного влияния на вашу производительность (если вы беспокоитесь), вы можете вернуть его по значению.

// don't need the global variable anymore
std::vector<int> some_function(std::vector<int> &input)
{
    std::vector<int> result;
    // do something
    return result;
}

int main()  // main returns int, not void
{
    std::vector<int> input;
    // insert some values
    std::vector<int> output = some_function(input);
    return 0;
}

Больше не нужно беспокоиться о том, кто отвечает за распределение и освобождение памяти. Ваш код становится понятнее и безопаснее исключений.

3 голосов
/ 05 апреля 2010

Я думаю, что второй вариант лучше, потому что у вас "сбалансированная ответственность за указатель". Это делает код более читабельным, потому что вы видите, где вы размещаете и где вы освобождаете свою память.
Если вы хотите использовать первый вариант, я бы предложил вам сделать двойную функцию some_function_free(). Что касается malloc / free, new / delete, new[] / delete[] и т. Д. Даже при том, что это будет просто delete[], с помощью этого вы сэкономите время, когда хотите изменить способ выделения памяти.

1 голос
/ 05 апреля 2010

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

0 голосов
/ 06 апреля 2010

Есть еще одно преимущество для второго в том, что оно не требует выделения кучи.Вы можете вызвать код, используя только выделенную память стека:

int main()
{
    int input[10];
    int output[10];

    some_function(input, output);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...