Member Function返回错误的智能指针

时间:2016-02-22 21:57:55

标签: c++ pointers shared-ptr smart-pointers

我使用现代C++创建一个非常简单的游戏引擎,采用旧的基于文本的冒险风格。

我有这样的Room类:

class Room
{
public:
    Room(void);
    void connect(shared_ptr<Room> room, Direction direction);

private:
    std::shared_ptr<Room> north;
    std::shared_ptr<Room> south;
    std::shared_ptr<Room> east;
    std::shared_ptr<Room> west;
};

connect()基本上是northsouth等指针的设定者。 它看起来像这样:

void Room::connect(std::shared_ptr<Room> room, Direction direction)
{
    switch (direction)
    {
        case Direction::NORTH:
            this->north = room;
            break;
        case Direction::SOUTH:
            this->south = room;
            break;
        case Direction::EAST:
            this->east = room;
            break;
        case Direction::WEST:
            this->west = room;
            break;
        default:
            std::cerr << "[ERROR] Invalid direction" << std::endl;
    }
}

现在我可以致电

Room example_room{};
Room another_room{};

example_room.connect(std::make_shared<Room>(another_room), Direction::NORTH)
another_room.connect(std::make_shared<Room>(example_room), Direction::SOUTH)

当我启动lldb并查看变量时,example_room::north将是指向std::shared_ptr<Room>对象的Room,但是,此对象并非如此似乎是another_room,因为其south数据成员是std::shared_ptr,其中包含nullptr

所以他们指向其他房间,但他们并没有指向对方。我知道原因必须在connect()成员函数的某处,但我不知道在哪里。

2 个答案:

答案 0 :(得分:3)

make_shared从调用它的参数创建一个新对象,并返回指向新对象的shared_ptr。在示例代码中,它使两个原始房间的副本。这不是我们需要的东西。事实上,共享指针在这个应用程序中是错误的。将有几个属于应用程序的房间,它们应该在全局或某种管理其生命周期的容器中定义。每个房间都应该有一个指向邻居的普通指针。没有任何空间来管理其邻居的生命。这是应用程序的责任。

答案 1 :(得分:0)

您正在堆栈上创建example_roomanother_room个实例,但是要connect()您使用make_shared()传递在堆上创建的全新实例。让example_roomanother_roomshared_ptr可以,但是!正如@PiotrSkotnicki在评论中提到的那样,您不应该使用shared_ptr进行通告依赖性。使用weak_ptr代替Room成员。

e.g:

class Room
{
public:
    // ...
    void connect(weak_ptr<Room> room, Direction direction);
private:
    std::weak_ptr<Room> north;
    std::weak_ptr<Room> south;
    // ...
}

然后:

auto example_room = std::make_shared<Room>();
auto another_room = std::make_shared<Room>();

example_room->connect(another_room, Direction::NORTH)
another_room->connect(example_room, Direction::SOUTH)

只要您需要这些链接,请确保原始shared_ptr保持活着状态。