[英]c++ vector of class object pointers
我要做的基本上是創建兩個對象向量,其中一些對象同時輸入到兩個列表中,而另一些則剛剛輸入到一個列表中。 我發現的第一個問題是,當我使用push_back()將一個對象添加到兩個列表中時,該對象已被復制,因此當我從一個列表中對其進行更改時,該對象在另一個列表中不會發生變化。 為了解決這個問題,我嘗試創建一個指向對象的指針列表作為列表之一。 但是,當我稍后在數據上訪問指針時似乎已損壞,則數據成員值都錯誤。 以下是我的代碼片段:
向量的定義:
vector<AbsorbMesh> meshList;
vector<AbsorbMesh*> absorbList;
...向兩個對象添加對象:
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
// Add to the absorption list
absorbList.push_back(&nurbsMesh);
// Store the mesh in the scene list
meshList.push_back(nurbsMesh);
訪問對象:
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0]->receivedPower;
}
我究竟做錯了什么?
缺少一些細節,但這只是一個猜測。
nurbsMesh
在push_back
和absorbList[0]->receivedPower
之間超出范圍。
因此,現在您的指針向量包含一個指向不再存在的對象的指針。
嘗試將復制構造函數添加到您的AbsorbMesh類中,然后將其添加到向量中。
absorbList.push_back(new AbsorbMesh(nurbsMesh));
meshList.push_back(nurbsMesh);
別忘了像這樣刪除absorbList
的對象
for(vector<AbsorbMesh*>::iterator it = absorbList.begin(); it != absorbList.end(); it++) {
delete it;
}
或者將共享指針存儲在向量中,而不是裸指針。 如果您感興趣的話,Boost具有良好的共享指針實現。 在這里查看文檔
如果要更新一個向量中的項目,而修改另一向量中的對象,則需要在兩個向量中存儲指針。
使用您的原始要求(更新一個向量中的項目會影響另一向量中的項目,這就是我使用boost共享指針的方式(警告,未經測試的代碼)
vector<boost::shared_ptr<AbsorbMesh> > meshList;
vector<boost::shared_ptr<AbsorbMesh> > absorbList;
boost::shared_ptr<AbsorbMesh> nurb = new AbsorbMesh(nurbs.CreateMesh(uStride, vStride));
meshList.push_back(nurb);
absorbList.push_back(nurb);
...
...
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0].get()->receivedPower;
}
您正在存儲分配在堆棧上的對象的地址。 只要您的push_back()
結束, nurbsMesh
對象就會被銷毀。 如果以后嘗試訪問此指針,則該對象已被破壞並包含垃圾。 您需要保留即使功能超出范圍仍保留的對象。 為此,使用new
為堆中的對象分配內存。 但是對於每一個新的,您都應該有一個相應的delete
。 但是在您的情況下,將同一個指針推入兩個向量時,將其刪除會遇到問題。 為了解決這個問題,您將需要某種類型引用計數機制。
當您嘗試從向量獲取指針時,對象被刪除。
嘗試做
vector.push_back(new Object);
解決了其他人提到的問題(將指針存儲到堆棧上的對象)后,您將遇到另一個問題。 vector
可能會重新分配,從而導致其內容移動到另一個位置。
因此,安全的方法是將指針存儲在兩個向量中。 然后,當然,您需要確保將其刪除...但是那是您的C ++。
absorbList.push_back(&nurbsMesh);
是錯的
absorbList
保存指向本地對象的指針。 當nurbMesh
被破壞時,您將無法編寫absorbList[0]->
但是,當我稍后訪問指針時,數據似乎已損壞
當您將某物放在矢量上時,矢量可能會將其從一個物理位置移動到另一個物理位置(尤其是在調整矢量大小時),這會使指向該對象的任何指針無效。
要解決此問題,您需要在兩個向量中存儲一個指針(可能是“智能指針”)(而不是讓一個向量按值包含對象)。
如果要執行此操作,則最好禁用對象的復制構造函數和賦值運算符(通過將它們聲明為私有,而不定義它們),以確保在創建對象后不能將其移動。
您的示例有幾處錯誤
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
該對象在堆棧上分配。 它是純本地對象。 當您到達由{}包圍的當前塊的末尾時,該對象將被銷毀。
absorbList.push_back(&nurbsMesh);
現在,您獲得了最有可能被破壞的對象的指針。
meshList.push_back(nurbsMesh)
這樣就在向量上復制了一個全新的對象。
同樣,首先將對象推到向量上,然后使用absorbList.push_back( &meshList.back() )
將指針推到向量上的對象也是錯誤的,因為vector::push_back
將重新分配整個向量,從而使所有指針無效。
你也許可以創造一切AbsorbMesh
第一對象,把它們到向量,然后拿到指針在矢量這些對象。 只要您不觸摸矢量,就可以了。
或者,使用new AbsorbMesh()
在堆上創建對象,但確保對由此創建的每個指針調用delete
。 否則,您將發生內存泄漏。
第三種解決方案,避免麻煩,並使用可幫助您破壞對象的智能指針 。
首先,正如其他人指出的那樣,您不能在堆棧上分配對象(即,不是通過new
或類似方法),而是在離開作用域之后將它們放到周圍。
其次,將對象放在STL容器中並維護指向它們的指針非常棘手,因為容器可以移動對象。 通常這是一個壞主意。
第三,由於無法復制auto_ptrs,因此auto_ptr<>
根本無法在STL容器中使用。
指向獨立分配的對象的指針可以工作,但是在正確的時間刪除它們很棘手。
最有效的方法是shared_ptr<>
。 使每個向量成為vector<shared_ptr<AbsorbMesh> >
,並通過new
分配,並且以很少的性能代價就避免了很多麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.