[英]Issue passing std::unique_ptr's
在過去的一個小時中一直停留在此代碼上,仍然試圖讓我領悟並實現智能指針,但是這個問題使我很困惑。
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>'
您需要使用std::move
將所有權從addEntity
傳遞給Add
:
if(gameObject->isCollidable()){
_actors.Add(std::move(gameObject));
} else {
_props.Add(std::move(gameObject));
}
如果未明確允許將其從中移出,則無法傳遞unique_ptr
。 這就是使其成為唯一指針的原因。 如果可以復制它,則原件和副本都將指向同一對象。 當您離開它時,原始指針將放棄對新指針的所有權。
您正在嘗試將unique_ptr
左值傳遞給按value接受unique_ptr
的函數 ,這將導致創建該指針的副本 :這是有意禁止的。 唯一指針用於對唯一所有權進行建模:這意味着持有唯一指針的實體具有指向對象的所有權。
在周圍復制一個唯一的指針將意味着在系統中散布多個擁有的指針:這當然會破壞唯一所有權的目的,這解釋了為什么您不能復制唯一的指針。
您可以做的是轉移此所有權,因此,如果調用一個接受唯一指針的函數,則可以在將unique_ptr
作為參數傳遞給該函數時移動它:
_actors.Add(std::move(gameObject));
// ^^^^^^^^^
請注意,通過移離唯一指針來轉移所有權意味着調用者函數被留有“僵屍”唯一指針對象,該對象不再擁有先前指向的對象:因此,調用者函數不應嘗試對其進行取消引用了。
您不能按值傳遞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)
// ^^^
現在,您可以像現在一樣調用該方法,這將僅導致一次所有權轉移(到_gameObjects
的pair
)。
但是,正如@Xeo在評論中指出的那樣,第二種選擇違反了最佳實踐的經驗法則,即: 所有權轉讓在所有時候都應明確 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.