簡體   English   中英

在堆棧上創建一個對象,然后通過引用傳遞給C ++中的另一個方法

[英]Creating an object on the stack then passing by reference to another method in C++

我來自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. 什么是將堆棧對象傳遞給將它們存儲為指針的方法的正確方法?

我意識到這些對C ++程序員來說可能是顯而易見的。

標記

  1. 是。
  2. 指針保持“活着”,但指向不再存在的對象。 這意味着,當您第一次嘗試取消引用此類指針時,您將進入未定義的行為(可能您的程序將崩潰,或者更糟糕的是,將繼續運行給出“奇怪”結果)。
  3. 如果要在返回函數后保留它們,則根本不這樣做。 這就是使用堆分配和存儲對象副本的容器的原因。

實現您要做的事情的最簡單方法是將對象的副本存儲在普通的STL容器中(例如std::vector )。 answer ). 如果這些對象重量級且復制成本 ,您可能希望在堆上分配它們將它們存儲在容納足夠智能指針的容器中,例如boost::shared_ptr (請參閱@ 答案中的示例)。

另一種可能性是將boost::ptr_vectorboost::ptr_vector_owner結合使用; 最后一個類負責“擁有”存儲在關聯的ptr_vector的對象,並在超出范圍時刪除所有指針。 有關ptr_vectorptr_vector_owner更多信息,您可能需要查看本文

要實現您的目標,您應該使用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;
}

是的,一旦你的函數離開范圍,你的對象將從堆棧中彈出。 您應該使用new創建一個堆對象,並在向量中添加指向該對象的指針。

如前所述,一旦第一個函數超出范圍,向量中的指針將指向未定義的內容

該代碼將無法編譯,因為在Add函數中,您試圖將整個對象推送到需要指向對象的指針的向量中。

如果您要獲取該對象的地址並將其推送到向量上,那么這將是危險的,因為原始對象很快將從堆棧彈出,並且您存儲的指針將指向未初始化的內存。

如果你使用普通向量而不是指針向量,則push_back調用將復制整個對象而不是指針,因此它是安全的。 但是,這並不一定有效,對於來自C#,Java或Python世界的人來說,“復制一切”方法可能並不直觀。

為了存儲指向對象的指針,必須使用new創建它。 否則它會在超出范圍時消失。
這里介紹的問題最簡單的解決方案是使用std :: vector而不是boost :: ptr_vector,因為這樣push_back會復制向量中的對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM