2013-04-14 101 views
0

在過去的一小時內一直停留在這段代碼上,仍然試圖讓我的腦袋圍繞着智能指針並實現它們,但是這個問題已經讓我很難過了。發出通過std :: unique_ptr的

void GameState::addEntity(std::unique_ptr<Entity> gameObject) 
{ 
    if(gameObject->isCollidable()){ 
     _actors.Add(gameObject); 
    } else { 
     _props.Add(gameObject); 
    } 
} 

// This is the method the above function is trying to call. 
void GameObjectManager::Add(std::unique_ptr<Entity> gameObject) 
{ 
    _gameObjects.insert(std::make_pair(ID, std::move(gameObject))); 
    ID++; 
} 

我收到的錯誤信息是;

'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 

回答

1

您無法通過值unique_ptr。以下是試圖建立一個unique_ptr,這是被禁止的副本:

if(gameObject->isCollidable()){ 
    _actors.Add(gameObject);  // THIS LINE 
} else { 
    _props.Add(gameObject);  // and THIS LINE 
} 

一個解決方案是通過與std::move()

if(gameObject->isCollidable()){ 
    _actors.Add(std::move(gameObject)); 
//    ^^^^^^^^^ 
} else { 
    _props.Add(std::move(gameObject)); 
//    ^^^^^^^^^ 
} 

這將導致兩個所有權轉讓。一個是std::unique_ptr<Entity>,它是GameObjectManager::Add的輸入參數,另一個是_gameObjects中的std::pair

另一種解決方案是修改的GameObjectManager::Add簽名得到一個參考:

void GameObjectManager::Add(std::unique_ptr<Entity> & gameObject) 
//             ^^^ 

現在,你可以調用方法,你正在做的,這將導致只有一個所有權轉移(到pair in _gameObjects)。

但是,正如@Xeo在評論中指出的那樣,第二個選項違反了最佳做法經驗法則:所有權轉讓應該在所有點都明確

+3

所有權轉讓應在所有點明確。 – Xeo

+0

你是指Xeo,會不會使用參考方法進行惡作劇? – user1725794

+0

@ user1725794:這將是微妙的。獨特指針的所有權轉讓應始終明確。這樣你最終會得到兩個共享一個唯一指針的例程,這種類型會破壞'unique_ptr'的目的(即對象應該一次擁有*一個*實體)。順便說一句,如果你想通知某個用戶,你必須在用戶名之前使用'@'字符。 –

3

您需要使用std::moveaddEntity通過所有權Add

if(gameObject->isCollidable()){ 
    _actors.Add(std::move(gameObject)); 
} else { 
    _props.Add(std::move(gameObject)); 
} 

你不能傳遞一個unique_ptr沒有明確允許其從移動。這是什麼使它成爲一個獨特的指針。如果您可以複製它,則原件和副本都將指向同一個對象。當你離開它時,原始指針會放棄對新的指針的所有權。

+1

如果您明確允許將其從中移除,則不再是副本:P – Xeo

+0

哦,太棒了!感謝修復! – user1725794

+0

@Xeo好點! –

1

您嘗試將unique_ptr左值傳遞給這需要一個功能unique_ptr按值,這將導致創建指針的副本:這是有意禁止。獨特的指針是爲了模擬獨特的所有權:這意味着持有唯一指針的實體擁有指向對象的所有權。

複製一個獨特的指針將意味着有幾個擁有指針遍佈整個系統:這當然會擊敗獨特所有權的目的本身,這就解釋了爲什麼你不能複製唯一的指針。

你可以做的是轉移這個所有權,所以如果你調用接受的唯一指針的函數,你可以移動unique_ptr,當你把它作爲一個參數傳遞給函數:

_actors.Add(std::move(gameObject)); 
//   ^^^^^^^^^ 

請注意,通過從一個唯一指針移開意味着調用者函數留下了一個「殭屍」唯一指針對象,該對象不再擁有它先前指向的對象:因此,調用者函數應該不要試圖解除引用它了。