是在堆栈或堆上分配的不使用“新”分配的对象
Posted
技术标签:
【中文标题】是在堆栈或堆上分配的不使用“新”分配的对象【英文标题】:are objects allocated without using "new" allocated on stack or heap 【发布时间】:2017-02-21 14:54:12 【问题描述】:我是 C++ 新手,所以问题很简单。
假设我已经定义了一个类 Foo,并在以下代码中创建了一个向量向量:
namespace testme
class Foo
public:
Foo(int x): x_(x) ;
static vector<vector<int>> ReturnVecOfInts(int num)
vector<vector<int>> ret(num);
for (int i = 0; i < num; i++)
vector<int> tmp;
ret.push_back(tmp);
return ret;
当我打电话时:
Foo::ReturnVecOfInts(5)
是在堆或堆栈上创建的向量的向量。引用在堆栈上,但我想知道它是否指向堆,因为我想从函数中返回这个对象。
这对我很重要,因为很明显,如果将它们分配在堆栈上,向量的向量将超出范围,并且在被调用函数之外无法使用。
【问题讨论】:
完全取决于该声明所在的位置。如果它在命名空间范围内,则该对象具有静态存储持续时间,既不是堆栈也不是堆。顺便说一句,请不要发布幻想代码:发布真实代码。 c++ 标准中没有定义 stack 或 heap 之类的东西。 这取决于您使用的系统。这就是为什么 C++ 没有堆栈和堆的概念,而是使用自动和动态存储。 通常如果您在函数内部声明它在堆栈上。如果它在堆分配的对象内,那么它也在堆上。这在很大程度上取决于该语句出现的上下文。 所以你真正的问题是:按值返回本地对象是否安全?,是吗? 【参考方案1】:你可能想多了。
在你的情况下,你在这样的代码中是安全的:
Foo f = Bar::GetFoo();
当您从函数返回对象时,通常可能会发生各种优化(例如 RVO、NRVO 等),但最重要的是您的 f
对象可以安全使用。
即使在 Foo 内部你有一个像 std::vector
这样的数据成员,它通常从堆中分配它的内存(你可以使用自定义分配器自定义这种行为),这要归功于复制构造函数、移动构造函数、析构函数等。你完全安全地从函数返回它,或者复制 Foo 实例。
编辑我注意到您在我写完答案后更改了代码,返回 vector<vector<int>>
而不是 Foo
。同样,我写的内容仍然适用。
【讨论】:
从@Ryan Haining 的评论中,我了解到c++ 返回的是实际对象。返回 vectorvector
包装和管理一个动态分配的数组;可以安全地假设数组将在堆(或等效)上创建,管理部分(包括数组的地址)在堆栈(或等效)上;管理部分是唯一需要返回的东西,因为数组不会被释放。 [请注意,这适用于具有堆栈和堆的系统。更深奥的系统可能会以不同的方式处理std::vector
。另请注意,它在实践中的工作方式可能与此不同;这只是一个简单的描述。]
想象一下:你的客厅里有一台电视,你和你的朋友正在看它。你有遥控器。如果你想让你的朋友负责电视,你是把电视放在他腿上,还是把遥控器给他?以上是关于是在堆栈或堆上分配的不使用“新”分配的对象的主要内容,如果未能解决你的问题,请参考以下文章