C ++类指针和所有权

msm*_*114 -2 c++ pointers lifetime

因此,我在C ++中重新创建了Pong(将ncurses用于终端hijinks,因为尝试仅通过控制台来完成它比我想象的要难得多)。这已经有一段时间了,它的意思是“刷新C ++”,我想使用Unity进行一些Hobby游戏开发。

我想:“至少我应该先用C ++制作一个简单的游戏,以证明我什至可以从Unity开始。” Pong是您需要处理的明显选择:对象,游戏状态,碰撞,运动矢量。

在刷新C ++的过程中,我不得不查找许多新事物,并提醒自己一些被遗忘的事情(自接触C ++已有10年了)。我不太清楚的一件事是关于类的指针的详细信息。(顺便说一下,这里有一个非常基本的版本,包括球和桨/碰撞):https : //pastebin.com/5NHjEjxX到目前为止,我只花了几个小时。

具体来说,我在这里记不清一件事:

const int boardWidth = 60;
const int boardHeight = 12;
Ball ball = Ball(-1,1,(boardWidth/2),(boardHeight/2));
Ball *p_ball = &ball;
Paddle paddle1 = {4,(boardHeight/2),3};
Paddle *p_paddle1 = &paddle1;
Paddle paddle2 = {(boardWidth-4), (boardHeight/2),3};
Paddle *p_paddle2 = &paddle2;
Board board; 
Run Code Online (Sandbox Code Playgroud)

(这是在Game类初始化中。尽管我有点想知道是否应该将其放入构造函数中)。但是...。特别是当我声明Ball ball = Ball(-1,1,(boardWidth/2),(boardHeight/2));Paddle paddle1 = {4,(boardHeight/2),3};这些项“坐在”内存中在哪里?我承担堆?另外,我将如何以正确的方式删除这些内容(例如,球超出范围,我需要创建一个新球?)

我知道关于所有权的一些事情……我觉得这是使用&的错误方式,因为例如p_ball实际上不会“拥有”该类,而只是能够正确引用它?(我认为有一个术语“智能指针”,但是上次我接触C ++时还没有真正出现过)。如果有更合适的方法,我想知道!

我还被告知,无论如何都要避免在这些函数中通过引用传递引用,以避免使用指针并避免一起创建指针。

Mil*_*nek 5

所有这些都是自动变量。当您达到当前范围的末尾时,它们的生命周期将结束。无需删除它们;一旦您达到当前范围的末尾,该操作就会自动发生。


如果您希望您的Game类对象拥有球,桨和板,则它们具有成员作用域是有意义的。即

class Game {
public:
    static const int BOARD_WIDTH = 60;
    static const int BOARD_HEIGHT = 12;

    Game()
        : ball{-1, 1, BOARD_WIDTH / 2, BOARD_HEIGHT / 2},
          paddle1{4, BOARD_HEIGHT / 2, 3},
          paddle2{BOARD_WIDTH - 4, BOARD_HEIGHT / 2, 3}
    {}

private:
    Ball ball;
    Paddle paddle1;
    Paddle paddle2;
    Board board;
};
Run Code Online (Sandbox Code Playgroud)

这些成员对象将共享对象的生存期Game


指针只是指向其他对象的对象。它们不会影响它们指向的对象的寿命。例如,您可以从方法返回指向对象成员的指针。只要注意您的指针不会超出它们所指向的对象。

如果要使Game类包含指向其他对象的指针,则需要自己管理这些其他对象的生存期。例如,您可以动态分配它们。与直接将对象包含在对象中相比,这几乎没有什么优势Game,并且增加了大量的复杂性和开销。

在这里,我std::unique_ptr用于执行内存管理:

class Game {
public:
    static const int BOARD_WIDTH = 60;
    static const int BOARD_HEIGHT = 12;

    Game()
        : ball{std::make_unique<Ball>(-1, 1, BOARD_WIDTH / 2, BOARD_HEIGHT / 2)},
          paddle1{std::make_unique<Paddle>(4, BOARD_HEIGHT / 2, 3)},
          paddle2{std::make_unique<Paddle>(BOARD_WIDTH - 4, BOARD_HEIGHT / 2, 3)},
          board{std::make_unique<Board>()}
    {}

    // Copying is implicitly disallowed since std::unique_ptr is non-copyable.
    // You could implement a copy constructor and copy assignment operator to
    // do a deep copy

private:
    std::unique_ptr<Ball> ball;
    std::unique_ptr<Paddle> paddle1;
    std::unique_ptr<Paddle> paddle2;
    std::unique_ptr<Board> board;
};
Run Code Online (Sandbox Code Playgroud)

或者,如果您确实愿意,也可以手动进行内存管理,但是这样做几乎没有好处:

class Game {
public:
    static const int BOARD_WIDTH = 60;
    static const int BOARD_HEIGHT = 12;

    Game()
        : ball{new Ball(-1, 1, BOARD_WIDTH / 2, BOARD_HEIGHT / 2)},
          paddle1{new Paddle(4, BOARD_HEIGHT / 2, 3)},
          paddle2{new Paddle(BOARD_WIDTH - 4, BOARD_HEIGHT / 2, 3)},
          board{new Board()}
    {}

    // You must implement these yourself to do a deep copy when doing manual
    // memory management.  I've opted to delete them to disallow copying a Game object
    Game(const Game&) = delete;
    Game& operator=(const Game&) = delete;

    ~Game() {
        // every instance of 'new' must have exactly one matching 'delete'
        delete board;
        delete paddle2;
        delete paddle1;
        delete ball;
    }

private:
    Ball* ball;
    Paddle* paddle1;
    Paddle* paddle2;
    Board* board;
};
Run Code Online (Sandbox Code Playgroud)