成员函数返回错误的智能指针

Member Function returns wrong smart pointer

本文关键字:智能 指针 错误 函数 返回 成员      更新时间:2023-10-16

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

我有一个这样的房间类:

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将是一个指向Room对象的std::shared_ptr<Room>,但是,该对象似乎并不another_room,因为它south数据成员是包含nullptrstd::shared_ptr

所以他们指向其他房间,但他们不指向对方。我知道原因一定在connect()成员函数的某个地方,但我不知道在哪里。

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

您正在堆栈上创建example_roomanother_room实例,但为了connect(),您将传递在堆上创建的全新实例 make_shared() .让你的example_roomanother_room shared_ptr会起作用,但是!正如@PiotrSkotnicki在评论中提到的,您不应该将shared_ptr用于循环依赖。请改用weak_ptr Room成员。

例如:

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的活动。