簡體   English   中英

類對象指針的C ++向量

[英]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;
}

我究竟做錯了什么?

缺少一些細節,但這只是一個猜測。

nurbsMeshpush_backabsorbList[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.

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