C++ 对象存储在堆栈或堆中
Posted
技术标签:
【中文标题】C++ 对象存储在堆栈或堆中【英文标题】:C++ Object is stored in stack or heap 【发布时间】:2015-03-13 10:07:12 【问题描述】:我知道这个问题在 SO 中被问了很多,就像在 Object creation on the stack/heap? 据我了解,如果一个对象存储在 Stack 中,如果变量超出范围,它将被弹出。但是当涉及到自动存储时,它让我感到困惑,它怎么不在堆中。我读过不推荐在 C++ 中使用 new 和 delete (甚至邪恶是词的选择),因为它会引入内存泄漏。所以我设备了一个像这样的测试代码
#include <iostream>
#include <string>
class Cat
public:
Cat(const std::string& name)
this->name = name;
std::cout << "construct Cat " << this->name << std::endl;
~Cat()
std::cout << "destruct Cat " << this->name << std::endl;
void feed()
std::cout << "feed Cat " << this->name << std::endl;
private:
std::string name;
;
Cat createFelix()
Cat garfield("Garfield");
Cat felix("Felix");
garfield.feed();
felix.feed();
return felix;
void getAndFeedFelix()
Cat justFelix = createFelix();
justFelix.feed();
int main()
getAndFeedFelix();
std::cout << "bla bla blah" << std::endl;
结果是这样的
construct Cat Garfield
construct Cat Felix
feed Cat Garfield
feed Cat Felix
destruct Cat Garfield
feed Cat Felix
destruct Cat Felix
bla bla blah
所以在我的结论中,函数 createFelix()
是从 getAndFeedFelix()
调用的,它返回一个 Cat(存储在堆栈中),应该在函数返回后从堆栈中弹出,但对象在 @ 之后被破坏由于自动存储机制,987654326@ 超出范围。这怎么可能发生?如果自动存储使用堆和引用计数,那么它可能是可能的。我的逻辑错了吗?
【问题讨论】:
自动存储使用的是栈,而不是堆 如果你想查看所有细节,你应该实现一个检测的复制构造函数和赋值运算符。 “我读过不推荐在 C++ 中使用 new 和 delete(甚至邪恶是词的选择),因为它会引入内存泄漏”。说这话的人并没有在真正的项目上工作过。 @RSahu 我认为恰恰相反,在你从事一个真正的项目之后,你倾向于建议不要使用原始指针,而是使用智能指针。 @vsoftco,堆内存的使用是你工具箱中的一个工具。一旦你学会了如何使用该工具,它就不再可怕了。仅当您来自为您管理内存的语言时,这才令人恐惧。 【参考方案1】:你发现了Return Value Optimization(专门命名为返回值优化)。
这个函数:
Cat createFelix()
Cat felix("Felix");
return felix;
Cat justFelix = createFelix();
看起来它应该创建一个Cat
,复制它,然后销毁它。但作为优化,createFelix()
实际上在justFelix
拥有的内存中创建了felix
。所以我们只创建一个Cat
,零副本。这里的一切都在堆栈上。
那么:
void getAndFeedFelix()
Cat justFelix = createFelix(); // creates a cat
justFelix.feed(); // feeds a cat
// destroys a cat
你看到的输出是什么。
【讨论】:
那么您如何在函数createFelix()
中进行测试,以便将对象felix
存储在堆栈中?我避免直接使用return Cat("felix");
以避免这种优化
@MarcelDaryanto 为什么需要测试堆栈中是否存在某些东西? 100% 保证无需测试。
因为据我所知,如果一个对象位于堆栈中,它将在离开范围时被释放,在返回语句之后的函数调用中,所有分配的堆栈都将被弹出。因此,如果您想访问该对象以供以后使用,它将不可用,CMIIW。但是如果它使用诸如自动引用计数之类的智能指针并存储在堆中,只要有东西引用它就不会被释放
@MarcelDaryanto 不确定你想说什么。 (1) 这里的Everything都在栈上,因为你没有做any动态分配,所以它们必须在栈上。 (2A) 如果应用(可选)NRVO,felix
会在调用者为justFelix
预留的堆栈空间中创建,因此它们是 相同 对象;如果是这样,实际上没有本地可以破坏。 (2B) 如果没有应用 NRVO,felix
会在堆栈上分配并复制分配给justFelix
,而felix
仅在分配完成之后 被销毁。在任何情况下,堆或引用计数都不需要或相关。以上是关于C++ 对象存储在堆栈或堆中的主要内容,如果未能解决你的问题,请参考以下文章