3

I created a vector of vector of shared_ptr class (_cells).

class Goban
{
  public:
    Goban();
    ~Goban();
  private:
    vector<vector<shared_ptr<Cell>>> _cells;
};

I initialize like that :

Goban::Goban() : _cells(18, vector<shared_ptr<Cell>>(18, make_shared<Cell>()))
{
}

The problem is all pointers refer to the same pointer dynamically (If I understood correctly). So when I change an element in my class Cell using my vector, it changes all other elements.

Evg
  • 25,259
  • 5
  • 41
  • 83
Guillaume
  • 191
  • 10
  • 1
    Yep, that's what a shared_ptr does. – Eljay Nov 08 '19 at 01:52
  • I want separate pointer, I should use unique_ptr ? – Guillaume Nov 08 '19 at 01:55
  • If you just want a managed list of cells, and aren't trying to do something specific with smart pointers, just use `vector>`. Vector manages its own memory. – parktomatomi Nov 08 '19 at 02:09
  • To go a bit further on why it's behaving that way, The constructor you're using for `vector` _copies_ the argument you pass 18 times.`shared_ptr` increments a reference count each time it's copied, so that creates 18 references to the same cell. – parktomatomi Nov 08 '19 at 02:22

3 Answers3

4

The problem is all pointers refer to the same pointer dynamically

This is because you use the constructor of vector that makes N copies of the value argument. A copy of a shared pointer points to the shared object.

I want separate pointer

Then don't use that constructor of vector. You can write a loop that calls make_shared to create each element, and a loop to repeat that for each vector.

eerorika
  • 232,697
  • 12
  • 197
  • 326
2

To get 18x18 distinct shared_ptrs, the correct way to initialize _cells might be:

Goban::Goban() : _cells(18, std::vector<std::shared_ptr<Cell>>(18))) {
    for (auto& cs : _cells)
        for (auto& c : cs)
            c = std::make_shared<Cell>();
}

or

Goban::Goban() : _cells(18) {
    for (auto& cs : _cells) {
        cs.resize(18);
        for (auto& c : cs)
            c = std::make_shared<Cell>();
    }
}
Evg
  • 25,259
  • 5
  • 41
  • 83
1

Just explicitly initialize your vector in the constructor body instead of the initializer list.

Goban::Goban()
{
    for (int i = 0 ; i < 18; i++) {
        _cells.push_back(make_shared<Cell>());
    }
}
selbie
  • 100,020
  • 15
  • 103
  • 173