c++ - 将对象的地址添加到循环 vector 中

标签 c++ loops pointers

我需要创建几个对象并将它们放入一个列表中(我正在使用 std::vector )。另外,我需要列表项指向对象的地址,以便我对对象所做的更改也反射(reflect)在列表中。 但问题是,列表中的每个项目都指向循环中创建的最后一个对象。

    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]

最佳答案

(现代 C++ 更新在最后)

如果您习惯使用变量引用计数的其他语言,您可能会想到这一点

Grass g1;

在循环的每次迭代中创建一个新的“Grass”对象。事实并非如此,C++ 不是一种引用计数语言。

相反,它在堆栈上创建一个作用域局部变量。

因为您在循环中执行此操作,所以它可能每次都位于内存中的同一位置。

您需要:

  1. 不用指针,只需让容器成为 Grass 对象的容器:让容器为您处理分配。

  2. 使用 C++11 的 unique_ptr 和 C++14 的 make_unique 为循环的每次迭代动态创建 Grass 实例。当包含 unique_ptr 的 vector 超出范围时,它们将被自动释放。

  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

<小时/>

C++11 引入了 emplace_back,它允许您一次性分配和构造容器中的条目。

#include <vector>

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

    // because x and y are inside a private sub-struct,
    // we'll need a constructor to pass the values in.
    Grass(int x, int y) : position{x, y} {}
};


int main() {
    std::vector<Grass> grassList{};    // default initialized.

    static constexpr size_t dim = 10;  // name the constant (DIMension)

    grassList.reserve(dim);            // allocate memory in advance

    for (auto i = 0; i < dim; i++) {
        for(auto j = 0; j < dim; j++) {
            grassList.emplace_back(i, j);
        }
    }

    // no cleanup required
}

现场演示:https://gcc.godbolt.org/z/G1YsW7hMs

关于c++ - 将对象的地址添加到循环 vector 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36731985/

相关文章:

c++ - 重新分配大小未知的 const char 数组

c++ - 如何使用整数参数访问结构列表 (c++)?

C++ - 无法重载赋值运算符

java - IF 语句检查(无法正常工作)

c++结构图中的值确实以隐藏的方式发生变化

c++ - 如何删除 move 赋值运算符并保​​持与标准容器的兼容性?

php - 特殊类别帖子的不同循环

C - 没有使用参数指针获得正确的值

C++:int *x[5] 和 int (*x)[5] 有什么区别?

C- 交换结构数组内的字符串或数字的决策函数