从函数中获取输出动态分配数组的更好变体?

时间:2010-04-05 09:34:13

标签: c++ pointers memory-management

这是两个变种。第一:

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 个答案:

答案 0 :(得分:6)

第三种变体

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()); 

} 

答案 1 :(得分:3)

我认为第二种变体更好,因为你有“对指针的平衡责任”。这使得代码更具可读性,因为您可以看到分配的位置以及释放内存的位置 如果你想使用第一个变体,我建议你制作双重功能some_function_free()。至于malloc / freenew / deletenew[] / delete[]等等,即使这样做也很简单{{1}通过使用它,您可以节省您想要更改内存分配方式的时间。

答案 2 :(得分:3)

在出现异常时,这两种变体都不是首选的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 :(得分:1)

一般来说,如果可行的话,最好不要堆分配和返回对象。它会创建所有权问题,并使界面复杂化(调用者必须知道如何管理返回对象的生命周期)。它还会对内存分配器施加更大的压力,内存分配器又可以创建线程争用,并通过更明智地为事物分配空间来拒绝调用者避免此成本的机会。

答案 4 :(得分:0)

第二个的另一个好处是它不需要堆分配。您只能使用堆栈分配的内存来调用代码:

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

    some_function(input, output);
}