unique_ptr vs shared_ptr - 设计

时间:2018-02-01 09:25:51

标签: c++ c++11 design-patterns c++14 c++17

我正在写一个纸牌游戏。我有以下课程:Card,Deck,Player,Board,GameLogic。

Deck拥有unique_ptr卡的向量。然后从牌组中抽出牌并传递给牌手。然后玩家挑选一张牌并放......这里我有一个设计问题。因为到目前为止,拥有unique_ptr是完全没问题的。但后来我想把卡片传给Board和GameLogic。

目前我将unique_ptr转换为shared_ptr。但我发现它要么丑陋又不符合逻辑。

我认为正确使用指针非常重要,应该告诉你变量的生命周期。我做错了什么但不知道是什么......

你对如何解决它有什么建议吗?

4 个答案:

答案 0 :(得分:1)

按照自己的说法:

  

Deck拥有unique_ptr卡的向量。然后从卡中抽出一张卡片   甲板并传递给球员。然后玩家拿起一张牌并放......这里   我有设计问题。因为到目前为止,拥有一个完全没问题   的unique_ptr。但后来我想把牌传给董事会和   GameLogic。

您可能在构造函数中创建了每张卡片。虽然这是完全可行的,但我没有看到这一点。只要总有相同,固定的卡数。我的意思是,你不会制作各种类型的新卡片。

我只是将卡片组创建为一个简单的数组,并将平均指针传递给玩家,依此类推。当甲板被摧毁时,卡片将被摧毁。

class Deck {
public:
    const static int NumCards = ...;
...
private:
    Card cards[NumCards];
};

class Player {
public:
    void dealt(Card*[] cards);
};

C ++的一个优点是允许您选择在堆或堆栈中存储对象。虽然前者更灵活(例如,当可用卡的数量随时间变化时),后者的效率要高得多,前提是你事先知道了项目的数量,就像你在这种情况下那样。

希望这有帮助。

答案 1 :(得分:1)

虽然我同意其他答案中的观点,即指针在这里并不是绝对必要的,但如果你使用指针,最简单的方法就是使用引用:

class Deck
{
private:
    std::vector<unique_ptr<Card>> cards;
public:
    const Card& get_card(unsigned index); // returns cards[index]
}

const引用允许您引用它而不必将其转换为shared_ptr(并且没有代码的其他部分修改它的风险)。

答案 2 :(得分:0)

如果您对共享指针和唯一指针都不满意,那么没有比普通指针更好的选择。使用观察者模式,当对象之间存在一对多依赖关系时,这种模式非常有用,这样当一个对象更改状态时,所有依赖项都会自动得到通知和更新。

答案 3 :(得分:0)

使用具有特定寿命的对象:

  • 首选指针值。根据需要复制值或传递引用,但不存储引用,因为可以删除引用的值。
  • 当需要指针时,如果您可以识别一个所有者,则更喜欢unique_pointer。根据需要传递引用,但不要存储它们。
  • 当有多个所有者或需要存储“引用”时使用shared_pointer。通过weak_pointers,可根据需要存储和锁定。

注意您也可以提供一些id作为参考,以便稍后,您可以访问可能已被删除的对象。如果你的Card只不过是一个id(心中的女王),那就把它复制一份。