簡體   English   中英

我應該使用const引用還是boost :: shared_ptr?

[英]Should I use a const reference or a boost::shared_ptr?

我創建了一些C ++類,以將紙牌游戲建模為學習練習。

我有SolitaireGame的類,CardStack(棋盤上的十堆紙牌之一)和一張紙牌。 我當前的模型表明SolitaireGame擁有104個Card對象的向量-我稱之為“鞋子”。 SolitaireGame還可以跟蹤10個CardStack,它們實際上是存儲在鞋子中的Card對象地址的雙端隊列。 Deck and Hand從CardStack繼承。 我通過指向存儲在鞋子中的原始對象的指針將卡片從Deck傳遞到Hand到Cascade。

根據我收到的關於問題的許多答案,我不應該通過指針傳遞Card的周圍,而應該使用const引用。 原因是存儲在矢量中的對象可以使它們的地址移動,因此將其地址存儲在任何地方都是禁止的。 我最近開始研究boost :: sharedptr。 人們對在這里使用shared_ptr到Card有什么想法?

這是類的簡化版本:

class SolitaireGame
{
    public: 
    SolitaireGame::SolitaireGame( int numsuits );       

    private:        
        vector<Card> _shoe;
        Deck _deck;
        Hand _hand;
        CardStack _cols[NUM_COLUMNS];
        int _numsuits;
        GameState   gamestate;
 };

class CardStack
{
    public:
        CardStack(){ cout << "CardStack constructor" << endl; }
        CardStack( const CardStack& );
        CardStack( const deque<Card *> &d );
        ~CardStack(){ }

        virtual Card * PullCard( Face f );
        virtual void PushCard( Card * c );

        Card * CardAt( int i ) const;
        Card * Top() const;

        deque<Card *>::iterator Begin() { return _cards.begin(); }
        deque<Card *>::iterator End() { return _cards.end(); }

        int Size() const;
        CardStack& operator=( const CardStack& rhs );

        friend std::ostream& operator<<(std::ostream &os, const CardStack &obj);

private:
        deque<Card *> _cards;

};

原因是存儲在矢量中的對象可以使它們的地址移動,因此將其地址存儲在任何地方都是禁止的。

出於相同的原因,存儲(常量)引用與存儲指針一樣糟糕。 如果只要其他對象持有指向其中對象的指針,向量的大小就不會改變,那么您應該是安全的。

使用C ++進行編程時,您應始終確定誰“擁有”一個對象,例如,由誰負責在不再需要該對象時將其刪除。 如果沒有自然對象所有者,則可以求助於像boost::shared_ptr這樣的智能指針,它們使用引用計數或垃圾回收來管理對象的生存期。

在您的情況下,很明顯SolitaryGame實例擁有所有卡。 此外,游戲中的卡數是固定的。 因此,您可以輕松地將牌的指針傳遞給依賴於游戲實例的對象。

刪除游戲后,所有卡都將被刪除,剩余指針將無效,但是此時,其他持有卡指針的對象也應被刪除。

是的,如果您要獲取您的元素的地址

vector<Card> _shoe;

並將它們放入您的

deque<Card *> _cards;

正如您所描述的,肯定有問題。 您的向量可能會重新分配,從而使向量的Card元素的地址不再有效。

傳遞對矢量內容的引用(const或其他方式)將具有與傳遞指針相同的問題。 在C ++中,引用實際上是一個薄薄的指針。 與指針的唯一區別在於其使用方式(作為別名)不能被“未seseed”,被設置為NULL,以及不能與別名類型區分開(您不能擁有別名)。卡參考的向量)。 引用沒有任何特殊的引用計數或您使用其他垃圾收集語言獲得的任何內容。 因此,當向量重新分配時,如果有人持有對卡片組中任何卡的引用,則這些引用將像指針一樣容易失敗。

用boost :: shared_ptr的Cards替換向量可以解決您的問題。 一個boost :: shared_ptr被引用計數。 這意味着它會跟蹤基礎對象存在多少個引薦來源。 您的向量將是shared_ptrs的向量,而不是對象本身的向量。 因此,當重新分配向量時,您只是在重新分配期間臨時將新的引薦來源者添加回基礎對象,然后向量將居住在重新分配空間中的shared_ptr替換了shared_ptr。 基礎對象不動。

我將更進一步,建議不要給每個人一個shared_ptr。 boost :: weak_ptr傳遞給非所有者。 boost :: weak_ptr是對基礎數據的弱引用。 當需要時,weak_ptr為某人提供了一個獲取shared_ptr的句柄。 它不參與基礎數據的引用計數。 因此,您可以首先檢查基礎數據是否被所有者刪除。 然后,如果未刪除它,則獲取一個shared_ptr(參與引薦來源網址計數的臨時成員)並執行所需的操作。

您不能將引用存儲在容器中,因此,如果要共享訪問,則只能使用指針。 shared_ptr似乎毫無意義,因為您不希望管理內存。

但是,如果我制作了Card類,它將僅包含一個或兩個整數,並且將是不可變的(除非這些是可以更改其西裝和值的魔術卡)。 因此,我只會使用卡的副本。

返回時,您可能更喜歡引用(除非您要存儲指向返回值的指針,否則最終看起來會很奇怪)。 但就我個人而言,我只是按價值回報。

我認為上述問題的解決方法是費迪南德(Ferdinand)的解決方法,但我想在這種情況下對boost :: shared_ptr的使用進行評論。

如何 ,你的卡對象? 如果它們足夠小(例如幾個整數),那么復制卡本身可能會比使用boost :: shared_ptr好,因為復制boost :: shared_ptr並不便宜(由於引用計數上的線程同步)。 這基於不需要具有唯一標識的Card對象,例如,十個黑桃Card對象與其他對象一樣好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM