我通常不是 C++ 开发人员。我常用的语言都是垃圾收集的,它们为我工作,但 C++ 让我感兴趣。
关于返回动态分配的对象或结构,我有一两个问题。我的理解是它们必须动态分配,因此数据在堆中而不是堆栈中。如果我错了,请纠正我。
返回指针的最佳做法是什么?假设我正在编写一个库,我如何在代码中指示是否/何时应该删除返回的指针?如果我返回一个数组,我如何返回数组的大小?
这些不是我在 C# 或 javascript 中必须面对的问题。这些问题确实是双向的:如果我在使用别人的图书馆,我要寻找什么?
我通常不是 C++ 开发人员。我常用的语言都是垃圾收集的,它们为我工作,但 C++ 让我感兴趣。
关于返回动态分配的对象或结构,我有一两个问题。我的理解是它们必须动态分配,因此数据在堆中而不是堆栈中。如果我错了,请纠正我。
返回指针的最佳做法是什么?假设我正在编写一个库,我如何在代码中指示是否/何时应该删除返回的指针?如果我返回一个数组,我如何返回数组的大小?
这些不是我在 C# 或 javascript 中必须面对的问题。这些问题确实是双向的:如果我在使用别人的图书馆,我要寻找什么?
C++ 有一个成语叫做 RAII。这对您来说意味着您不必担心清理工作,并且资源将在代码中的定义点被释放。
例如,在函数中创建一个数组并返回它。这是一个没有 RAII 的典型实现(另一个是调用者分配内存并将其传入):
int *makeIntArray(std::size_t length) {
return new int[length];
}
现在调用者需要记住释放这个内存。将此与 RAII 版本进行比较:
std::vector<int> makeIntArray(std::size_t length) {
return std::vector<int>(length);
}
当向量超出范围时,由此返回的内存将被释放,这取决于调用者。除其他外,它还提供了一个size()
成员函数来获取元素的数量。
也就是说,最好尽可能保持不动态分配的东西。如果您需要返回一个结构,比如说Str
,只需按值返回它:
Str makeStr() {
return Str();
}
没有动态分配意味着没有额外的工作,无论是释放内存还是将其包装在某些东西中(如std::unique_ptr
本例中的智能指针)。
至于其他库,您需要阅读文档以确保您必须拥有它返回的内容。如果必须,您可以做的一件事是用它制作一个 RAII 对象。例如:
int *makeSomeInt(int value) {
return new int(value);
}
...
std::unique_ptr<int> myInt(makeSomeInt(5));
//memory freed when myInt goes out of scope
我看到克里斯已经提供了一个很好的答案。有几件事要补充:
远离在代码中分配动态内存。让动态内存分配(和释放)尽可能由库来完成。(见vector
上面的例子。)
如果你必须自己做动态内存分配,那么每个内存(即指针)都必须有一个所有者。内存的构造和销毁应该是所有者,其他人只能使用它。
如果您使用的是 C++11,请熟悉unique_ptr
,这是您最常需要的。
来自Dobb 博士:
C++11 中有很多很棒的特性,但 unique_ptr 在代码卫生领域脱颖而出。简单地说,这是动态创建对象的灵丹妙药。