在堆栈上创建一个对象,然后通过引用传递给C ++中的另一个方法

时间:2010-09-21 09:54:30

标签: c++ gcc boost memory-management

我来自C#背景到C ++。假设我有一个方法在堆栈的方法中创建一个对象,然后我将它传递给另一个类方法,该方法将它添加到一个memeber向量。

void DoStuff()
{
    SimpleObj so = SimpleObj("Data", 4);
    memobj.Add(so); 
}

//In memobj
void Add(SimpleObj& so)
{
   memVec.push_back(so); //boost::ptr_vector object
}

以下是我的问题:

  1. 一旦DoStuff方法结束,那么它会超出范围并从堆栈中弹出吗?
  2. memVec有一个指向这样的指针,但它弹出了这里发生的事情?
  3. 将堆栈对象传递给将它们存储为指针的方法的正确方法是什么?
  4. 我意识到这些对C ++程序员来说可能是显而易见的。

    标记

5 个答案:

答案 0 :(得分:9)

  1. 指针保持“活着”,但指向不再存在的对象。这意味着,当您第一次尝试取消引用此类指针时,您将进入未定义的行为(可能您的程序将崩溃,或者更糟糕的是,将继续运行会产生“奇怪”结果)。
  2. 如果要在返回函数后保留它们,则根本不这样做。这就是使用堆分配和存储副本对象的容器的原因。
  3. 实现您尝试执行的操作的最简单方法是将对象的副本存储在普通STL容器中(例如std::vector)。如果这些对象是重量级的并且复制成本很高,那么您可能希望在堆上分配它们将它们存储在具有足够智能指针的容器中,例如, boost::shared_ptr(请参阅@Space_C0wb0y's answer中的示例)。

    另一种可能性是将boost::ptr_vectorboost::ptr_vector_owner结合使用;最后一个类负责“拥有”存储在关联的ptr_vector中的对象,并在超出范围时删除所有指针。有关ptr_vectorptr_vector_owner的详细信息,您可能需要查看this article

答案 1 :(得分:3)

要实现目标,您应该使用shared_ptr

void DoStuff()
{
    boost::shared_ptr<SimpleObj> so(new SimpleObj("Data", 4));
    memobj.Add(so); 
}

//In memobj
void Add(boost::shared_ptr<SimpleObj> so)
{
   memVec.push_back(so); // std::vector<boost::shared_ptr<SimpleObj> > memVec;
}

答案 2 :(得分:1)

是的,一旦你的函数离开范围,你的对象就会从堆栈中弹出。您应该使用new创建一个堆对象,并在向量中添加一个指针。

如前所述,当你的第一个函数超出范围时,向量中的指针将指向未定义的东西

答案 3 :(得分:1)

该代码无法编译,因为在Add函数中,您试图将整个对象推送到需要指向对象的指针的向量中。

如果您要获取该对象的地址并将其推送到向量上,那么这将是危险的,因为原始对象很快将从堆栈中弹出,并且您存储的指针将指向未初始化的内存。 / p>

如果你使用普通向量而不是指针向量,则push_back调用将复制整个对象而不是指针,因此它是安全的。但是,这并不一定有效,对于来自C#,Java或Python世界的人来说,“复制一切”方法可能并不直观。

答案 4 :(得分:0)

为了存储指向对象的指针,必须使用new创建它。否则它会在超出范围时消失。
这里介绍的问题最简单的解决方案是使用std :: vector而不是boost :: ptr_vector,因为这样push_back会复制向量中的对象