我需要创建几个对象并将它们放在一个列表中(我正在使用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]
答案 0 :(得分: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);
}
}
答案 1 :(得分:2)
如果您习惯使用其他使用变量计数的语言,那么您可能已经预料到了
Grass g1;
正在创造一个新的&#34; Grass&#34;对象循环的每次迭代。不是,C ++不是一种重新计算的语言。
相反,它会在堆栈上创建范围的局部变量。
因为您在循环中执行此操作,所以每次都可能在内存中的相同位置。
您需要:
只需将容器作为Grass对象的容器,而不是指针:让容器为您处理分配。
使用C ++ 11的unique_ptr
和C ++ 14&#39; make_unique
为循环的每次迭代动态创建Grass的实例。当包含unique_ptrs的向量超出范围时,它们将自动释放。
使用new
和delete
关键字手动分配和释放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);
}
}
}
选项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));
}
}
}
选项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();
}
答案 2 :(得分: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所示。