我正在使用现代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()
基本上是north
、south
等指针的二传手。它看起来像这样:
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
数据成员是包含nullptr
的std::shared_ptr
。
所以他们指向其他房间,但他们不指向对方。我知道原因一定在connect()
成员函数的某个地方,但我不知道在哪里。
make_shared
从调用它的参数创建一个新对象,并返回指向新对象的shared_ptr
。在示例代码中,它复制了两个原始房间。这不是这里需要的。事实上,共享指针在此应用程序中是错误的。将有多个属于应用程序的房间,它们应全局定义或在管理其生存期的某种容器中定义。每个房间都应该有一个指向其邻居的普通指针。不需要任何空间来管理其邻居的生命周期。这是应用程序的责任。
您正在堆栈上创建example_room
和another_room
实例,但为了connect()
,您将传递在堆上创建的全新实例 make_shared()
.让你的example_room
和another_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
的活动。