2016-04-20 51 views
2

我需要創建幾個對象並將它們放入列表中(爲此我使用std :: vector)。此外,我需要列表項指向對象的地址,以便我對對象所做的更改也反映在列表中。 但事情是,列表中的每個項目都指向循環中創建的最後一個對象。將對象的地址添加到循環中的向量中

for(int i=0;i<50;i++){ 
     for(int j=0;j<50;j++){ 
      Grass g1; 
      g1.position.x = i; 
      g1.position.y = j; 
      grassList.push_back(&g1); 
     } 
    } 

在列表中應該是草對象的屬性..

[0,0] 
[0,1] 
[0,2] 
. 
. 
. 
. 
[49,49] 

但它出來是..

[49,49] 
[49,49] 
[49,49] 
[49,49] 
. 
. 
. 
[49,49] 
+2

要麼通過推值,或者創建一個新的草對象(如在使用「新」運算符)。 g1是在堆棧上創建的,並且基本上是您一遍又一遍地使用其地址的相同對象。 – OldProgrammer

回答

0

如果任何(未指定)的原因,你需要存儲指向物體位置的指針,你需要這個

std::vector<Grass*> grassList; // Assumed you already have something like this 
for(int i=0;i<50;i++){ 
    for(int j=0;j<50;j++){ 
     Grass* gp1 = new Grass; 
     gp1->position.x = i; 
     gp1->position.y = j; 
     grassList.push_back(gp1); 
    } 
} 

這可以避免破壞正在存儲的指針所指向的對象。例如,請參閱Creating an object: with or without `new` 您必須注意用delete合適地刪除對象以釋放內存。

但是,根據您的需要,您也可以使用tuple_cat建議的一組對象而不是指針數組。

3

您正在將指向的局部變量指向該向量。局部變量在其範圍的末尾被銷燬(在這種情況下,倒數第二個})。因此,在}之後取消引用任何這些指針是未定義的行爲。您看到的輸出是未定義行爲的完全有效結果。

在這裏使用指針只是沒有意義。只有在需要絕對時才使用它們(包括new)。欲瞭解更多信息,請參閱Why should I use a pointer rather than the object itself?

這是正確的方式:

std::vector<Grass> grassList; 
     // ^^^^^ not pointers! 

for(int i=0; i<50; ++i) { 
    for(int j=0; j<50; ++j) { 
     Grass g1; 
     g1.position.x = i; 
     g1.position.y = j; 
     grassList.push_back(g1); 
    } 
} 
+0

「*在這裏使用指針只是沒有意義*」可能太絕對了。在大多數情況下,使用對象矢量很可能會工作得很好,但OP *的特定需求可能不會被覆蓋。在被鏈接的問題中接受的答案更爲謹慎:「*您只需要在需要時使用動態存儲持續時間。」 –

+0

我在開始時並未使用指針。我做的和你上面寫的完全一樣。但問題是,當我在代碼的其餘部分(向量列表之外)對這些對象進行更改時,它們沒有反映在列表中(出於顯而易見的原因)。也許我應該直接引用列表本身的對象。感謝您的澄清。 –

2

如果你習慣於使用的變量裁判計數其他語言,你可能會認爲

Grass g1; 

正在循環的每次迭代中創建一個新的「Grass」對象。事實並非如此,C++不是一種重新計算的語言。

相反,它在堆棧上創建了一個作用域局部變量。

因爲你在循環中這樣做,它可能每次都在內存中的相同位置。

你要麼需要:

  1. 取而代之的指針,只要你的容器草對象的容器:讓容器手柄分配給你的。

  2. 使用C++ 11的unique_ptr和C++ 14的make_unique爲循環的每次迭代動態地創建一個Grass實例。當包含unique_ptrs的向量超出範圍時,它們將被自動釋放。

  3. 使用newdelete關鍵字來手動分配和釋放Grass對象以指向。

選項1:

#include <vector> 

struct Grass { 
    struct { 
     int x, y; 
    } position; 
}; 

int main() { 
    std::vector<Grass> grassList; 
    for(int i=0;i<50;i++){ 
     for(int j=0;j<50;j++){ 
      Grass g1; 
      g1.position.x = i; 
      g1.position.y = j; 
      grassList.push_back(g1); 
     } 
    } 
} 

現場演示:http://ideone.com/DQs3VA

選項2:

#include <memory> 
#include <vector> 

struct Grass { 
    struct { 
     int x, y; 
    } position; 
}; 

int main() { 
    std::vector<std::unique_ptr<Grass>> grassList; 
    for(int i=0;i<50;i++){ 
     for(int j=0;j<50;j++){ 
      auto g1 = std::make_unique<Grass>(); 
      g1->position.x = i; 
      g1->position.y = j; 
      grassList.push_back(std::move(g1)); 
     } 
    } 
} 

現場演示:http://ideone.com/hJUdwR

選項3:

#include <vector> 

struct Grass { 
    struct { 
     int x, y; 
    } position; 
}; 

int main() { 
    std::vector<Grass*> grassList; 
    for(int i=0;i<50;i++){ 
     for(int j=0;j<50;j++){ 
      Grass* g1 = new Grass; 
      g1->position.x = i; 
      g1->position.y = j; 
      grassList.push_back(g1); 
     } 
    } 
    // ... 
    for (auto& g1: grassList) { 
     delete g1; 
    } 
    grassList.clear(); 
} 

現場演示:http://ideone.com/GTk7ON

+0

'std :: list'?真? - [爲什麼你應該避免鏈接列表](https://youtu.be/YQs6IC-vgmo)。 – emlai

+0

@tuple_cat根據他的命名,猜測他使用的是什麼容器。不是我選擇的容器。 – kfsone

+0

我很高興知道這不是你選擇的容器,但我想知道你爲什麼在你的例子中使用它。此外,引用OP:「我正在使用std :: vector」 – emlai

相關問題