Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unique_ptr vs shared_ptr - design [closed]

I'm writing a card game. I have the following classes: Card, Deck, Player, Board, GameLogic.

Deck holds a vector of unique_ptr Cards. Then a card is drawn from the deck and passed to a player. Then player picks a card and puts... Here I have a design problem. Because up to now it's totally fine to have a unique_ptr. But then I want to pass a card to both Board and GameLogic.

Currently I converted a unique_ptr to shared_ptr. But I find it either ugly and not logical.

I believe that proper usage of pointers is very important and should tell you about the lifetime of a variable. I'm doing something wrong but don't know what...

Do you have some suggestion about how to solve it?

like image 979
user2146414 Avatar asked Sep 20 '26 01:09

user2146414


2 Answers

To use objects with specific life spans:

  • Prefer values over pointers. Copy the values or pass references as needed, but don't store the references as the referenced value can be removed.
  • When pointers are needed, prefer unique_pointer if you can identify one owner. Pass references as needed, but don't store them.
  • Use shared_pointer when there are multiple owners or when "references" need to be stored. Pass weak_pointers, which can be stored and locked as needed.

Remark that you could also give some id as reference so later on, you could access objects that could have been removed. If your Card is nothing more than an id (queen of hearts), just pass a copy of it.

like image 196
stefaanv Avatar answered Sep 21 '26 15:09

stefaanv


Following your own words:

Deck holds a vector of unique_ptr Cards. Then a card is drawn from the deck and passed to a player. Then player picks a card and puts... Here I have a design problem. Because up to now it's totally fine to have a unique_ptr. But then I want to pass a card to both Board and GameLogic.

Probably you create each card in the constructor. Though it is perfectly feasible, I don't see the point. Provided there are always the same, fixed, number of cards. I mean, you don't create new cards of each type or whatever.

I would just create the deck of cards as a simple array, and pass average pointers to players and so on. The cards will be just destroyed when the deck is destroyed.

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

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

One of the advantages of C++ is that lets you choose between storing objects in the heap or the stack. While the former is more flexible (when the number of available cards changes over time, for example), the latter is much more efficient, provided you know the number of items beforehand, as apparently you do in this case.

Hope this helps.

like image 37
Baltasarq Avatar answered Sep 21 '26 14:09

Baltasarq