这是两个变种。第一:
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 ++函数都使用第二种变体。 第一个变体更舒适(在我看来)。但第二个也有一些优点(你在同一个块中分配和删除内存)。
也许这是一个愚蠢的问题但是哪种变体更好,为什么?
答案 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
/ free
,new
/ delete
,new[]
/ 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);
}