堆栈对象被插入容器?

时间:2013-01-09 21:37:33

标签: c++ vector

在C ++中,如果在堆栈上(在函数内)创建一个对象并将其插入堆分配容器(在函数完成后已传入函数/存在),会发生什么?

堆栈对象具有本地范围,但是它已插入的容器位于堆上,并且可以在函数(生成插入的位置)之后返回。在函数返回后,堆栈对象是否仍可从容器中检索?

void Test( std::vector<MyClass>& myvec )
{
    MyClass m;
    myvec.push_back(m);
}

6 个答案:

答案 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_ptrstd::shared_ptr

答案 5 :(得分:0)

在函数返回后,堆栈对象是否仍可从容器中检索?

仅当MyClass具有“gut”复制构造函数时。 (深层复制或分享其他resuorses的所有权等)

我的意思是,它可以被重新审视,但它可能处于经纪状态