std :: shared_ptr не обновляет свой счет - PullRequest
0 голосов
/ 02 апреля 2019

Я пытаюсь создать пользовательскую сеть class Tile внутри другого class Board, в котором хранится std::array<std::shared_ptr<Tile>, 34>.Я использую std::shared_ptr<Tile> объекты внутри class Tile, чтобы показать, какие узлы подключены.Однако, когда я инициализирую каждый из 34 Tile объектов, еще не инициализированные объекты, включенные в список, не обновляются с nullptr до их собственной ссылки.

#include <memory>
#include <array>
#include <cstddef>

struct Tile;
template <const std::size_t N> using TileLink  = std::array<const std::shared_ptr<const Tile>, N>;
template <const std::size_t N> using TileArray = std::array<std::shared_ptr<const Tile>, N>;

struct Tile {
    /* surrounding tiles */
    const std::size_t ID;
    const std::size_t num_adj;
    const TileLink<6> adjacent;
    Tile (std::size_t id, std::size_t n, const TileLink<6> & arr) : ID (id), num_adj (n), adjacent (arr) { }
    ~Tile (void) = default;
};

class Board {
private:
    TileArray<34> tiles;
public:
    Board (void);
    ~Board (void) = default;
};

Board :: Board (void) {
    /* Column 1 */
    tiles[0]  = std::make_shared<Tile> ( 0, 3, TileLink<6>{ tiles[1],  tiles[4],  tiles[5],  nullptr,   nullptr,   nullptr   });
    tiles[1]  = std::make_shared<Tile> ( 1, 4, TileLink<6>{ tiles[0],  tiles[2],  tiles[5],  tiles[6],  nullptr,   nullptr   });
    tiles[2]  = std::make_shared<Tile> ( 2, 3, TileLink<6>{ tiles[1],  tiles[6],  tiles[7],  nullptr,   nullptr,   nullptr   });
    /* Column 2 */
    tiles[3]  = std::make_shared<Tile> ( 3, 2, TileLink<6>{ tiles[4],  tiles[9],  nullptr,   nullptr,   nullptr,   nullptr   });
    tiles[4]  = std::make_shared<Tile> ( 4, 5, TileLink<6>{ tiles[0],  tiles[3],  tiles[5],  tiles[9],  tiles[10], nullptr   });
    tiles[5]  = std::make_shared<Tile> ( 5, 6, TileLink<6>{ tiles[0],  tiles[1],  tiles[4],  tiles[6],  tiles[10], tiles[11] });
    tiles[6]  = std::make_shared<Tile> ( 6, 6, TileLink<6>{ tiles[1],  tiles[2],  tiles[5],  tiles[7],  tiles[11], tiles[12] });
    tiles[7]  = std::make_shared<Tile> ( 7, 5, TileLink<6>{ tiles[2],  tiles[6],  tiles[8],  tiles[12], tiles[13], nullptr   });
    tiles[8]  = std::make_shared<Tile> ( 8, 2, TileLink<6>{ tiles[7],  tiles[13], nullptr,   nullptr,   nullptr,   nullptr   });
    /* Columns 4 - 6 */
    ...
    ...
    ...
    /* Column 7 */
    tiles[31] = std::make_shared<Tile> (31, 3, TileLink<6>{ tiles[26], tiles[27], tiles[32], nullptr,   nullptr,   nullptr   });
    tiles[32] = std::make_shared<Tile> (32, 4, TileLink<6>{ tiles[27], tiles[28], tiles[31], tiles[33], nullptr,   nullptr   });
    tiles[33] = std::make_shared<Tile> (33, 3, TileLink<6>{ tiles[28], tiles[29], tiles[32], nullptr,   nullptr,   nullptr   });
}

std::array IЯ перехожу к конструктору Tile не меняется.Как мне заставить его измениться?

Любая помощь будет принята с благодарностью.Извините за то, что я так долго задавал вопрос, я действительно не знал, как сделать этот пример меньше.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Здесь:

tiles[0]  = std::make_shared<Tile> ( 0, 3, TileLink<6>{ tiles[1],  tiles[4],  tiles[5],  nullptr,   nullptr,   nullptr   });

tiles[1], tiles[4] и т. Д. Еще не инициализированы и имеют значение shared_ptr для nullptr. Когда вы инициализируете tiles[1] позже, это не меняет то, что внутри tiles[0].

Вы полностью неправильно используете shared_ptr. Поскольку ваш массив плиток имеет фиксированный размер, просто выделите один раз всю необходимую память, а затем используйте не принадлежащие указатели. Поскольку есть владелец для памяти, и это Board.

0 голосов
/ 02 апреля 2019

Я решил свою проблему - спасибо @ t.niese и @fjardon за вашу помощь.

Мне пришлось сделать Tile более сложным, чтобы облегчить реальную проблему: что я не смог создатьуникальный Tile объект из std :: array в классе.Поэтому я добавил конструктор копирования и оператор присваивания, удалил интеллектуальные указатели и const -ness и сделал массив типа класса Tile.

class Tile;
template <const std::size_t N> using TileLink  = std::array<const Tile *, N>;
template <const std::size_t N> using TileArray = std::array<Tile, N>;

enum class OWNERSHIP { PLAYER_1, PLAYER_2, CONTESTED };

class Tile {
private:
    OWNERSHIP territory;
    /* surrounding tiles */
    std::size_t ID;
    std::size_t num_adj;
    TileLink<6> adjacent = { nullptr };
public:
    Tile (void) { }
    Tile (OWNERSHIP own, std::size_t id, std::size_t num, const TileLink<6> & arr);
    Tile (const Tile & rhs);
    Tile & operator = (Tile other);
    ~Tile (void) = default;
};

class Board {
private:
    TileArray<34> tiles;
    void create_col_1_and_7 (void);
    void create_col_2 (void);
    ...
    void create_col_6 (void);
public:
    Board (void);
    ~Board (void) = default;
};

Каждая из инициализаций теперь выглядит следующим образом:

tiles[0]  = Tile (OWNERSHIP::PLAYER_2,   0, 3, TileLink<6>{ &tiles[1],  &tiles[4],  &tiles[5],  nullptr,    nullptr,    nullptr    });
tiles[1]  = Tile (OWNERSHIP::CONTESTED,  1, 4, TileLink<6>{ &tiles[0],  &tiles[2],  &tiles[5],  &tiles[6],  nullptr,    nullptr    });
...
tiles[32] = Tile (OWNERSHIP::CONTESTED, 32, 4, TileLink<6>{ &tiles[27], &tiles[28], &tiles[31], &tiles[33], nullptr,    nullptr    });
tiles[33] = Tile (OWNERSHIP::PLAYER_1,  33, 3, TileLink<6>{ &tiles[28], &tiles[29], &tiles[32], nullptr,    nullptr,    nullptr    });
...