在C ++中,如果在堆栈上(在函数内)创建一个对象并将其插入堆分配容器(在函数完成后已传入函数/存在),会发生什么?
堆栈对象具有本地范围,但是它已插入的容器位于堆上,并且可以在函数(生成插入的位置)之后返回。在函数返回后,堆栈对象是否仍可从容器中检索?
void Test( std::vector<MyClass>& myvec )
{
MyClass m;
myvec.push_back(m);
}
答案 0 :(得分:4)
在这种特殊情况下,m
将被复制构造为MyClass
的新实例,该实例将由向量拥有。因此,可以从向量中检索不同但等效的 MyClass
实例,是的。
答案 1 :(得分:2)
Is the stack object still retrievable from the container after the function returns?
是的,您的myvec.push_back(m);
制作了m的副本,而新副本则由矢量管理。
但是,在函数返回后myvec
内部没有m
,因为您通过值将myvec
传递给Test函数,Test
函数会生成{的临时副本{1}}并将myvec
复制到其中,在函数返回后释放m
的临时副本。因此,您打算通过引用将myvec
传递给myvec
函数,如下所示:
Test
答案 2 :(得分:2)
基本假设:当您使用Vector
时,您的意思是std::vector
。答案可以更改为容器设计不同。
只要您喜欢通常应该这样做,并将对象(而不是指针)存储在容器中,您就可以了,因为存储在容器中的内容通常是您传递的对象的副本。
在正确的情况下,容器中的对象可以根据您传递的内容进行构造移动,但效果基本相同 - 您最终得到的对象的生命周期一直持续到从容器(或容器)中移除为止被毁坏等。)
答案 3 :(得分:0)
正如其他答案所述,m
被复制到向量中。也就是说,你的函数也按值接收向量(UPD:原始代码是真的,自那以后编辑过),显然不是你想要的。
答案 4 :(得分:0)
问题中的代码将在MyClass
中创建std::vector
的副本。当m
方法退出时,原始Test
将被销毁。
如果我们更改向量以存储指向MyClass
的指针,我们有两个可能的选项。
void Test( std::vector<MyClass*>& myvec )
{
// Allocates a new MyClass on the heap.
MyClass* pM = new MyClass();
myvec.push_back(pM);
// This variable will be allocated on the stack and cleaned up on method exit
MyClass dontDoThis;
myvec.push_back(&dontDoThis);
}
在此方法结束时,myvec
有两个元素,myvec[0]
和myvec[1]
。
当存储指针容器时,必须分配对象,以使其在指针位于容器中的时间长度内有效。在上面的示例中,pM
指针在Test
方法退出后有效。这意味着在方法退出后myvec[0]
将成为有效指针。
最初,一个指向dontDoThis
变量的有效指针将被添加到向量中,但是当方法退出时,将调用dontDoThis
的析构函数,并且内存可能会用于存储其他数据。 myvec
中的指针看起来没问题,但任何实际使用它的尝试都会导致未定义的行为。在方法退出时,myvec[1]
中的指针可能看起来有效,但实际上它指向垃圾。
请注意,稍后更改或删除myvec[0]
时,请务必致电:
delete myvec[0]
确保正确清理对象。否则会发生内存泄漏。
在解释裸指针会发生什么后,我强烈建议您使用智能指针,例如std::unique_ptr和std::shared_ptr
答案 5 :(得分:0)
在函数返回后,堆栈对象是否仍可从容器中检索?
仅当MyClass具有“gut”复制构造函数时。 (深层复制或分享其他resuorses的所有权等)
我的意思是,它可以被重新审视,但它可能处于经纪状态