过去一小时一直坚持使用这段代码,仍然试图了解智能指针并实现它们,但这个问题让我感到很难过。
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>'
答案 0 :(得分:3)
您需要使用addEntity
将所有权从Add
传递到std::move
:
if(gameObject->isCollidable()){
_actors.Add(std::move(gameObject));
} else {
_props.Add(std::move(gameObject));
}
如果没有明确允许移动unique_ptr
,则无法传递{{1}}。这使它成为一个独特的指针。如果你可以复制它,原始和副本都将指向同一个对象。当你离开它时,原始指针放弃了新指针的所有权。
答案 1 :(得分:1)
您正尝试将unique_ptr
左值传递给按值<{1}} 按值的函数,这将导致创建<该指针的strong> copy :这是故意禁止的。唯一指针用于模拟唯一所有权:这意味着拥有唯一指针的实体具有指向对象的所有权。
复制一个独特的指针意味着有几个拥有指针遍布整个系统:这当然会破坏独特所有权的目的本身,这就解释了为什么你不能复制唯一指针。
你可以做的是转移这个所有权,所以如果你调用一个接受唯一指针的函数,你可以移动 unique_ptr
当你将它作为参数传递给该函数:
unique_ptr
注意,通过从唯一指针移开来转移所有权意味着调用者函数留下了一个“僵尸”唯一指针对象,该对象不再拥有它先前指向的对象:因此,调用者函数不应该再尝试取消引用它。
答案 2 :(得分: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
的输入参数,一个是std::pair
中的_gameObjects
。
另一种解决方案是修改GameObjectManager::Add
的签名以获得参考:
void GameObjectManager::Add(std::unique_ptr<Entity> & gameObject)
// ^^^
现在,您可以按照目前的方式调用该方法,这样只会导致一次所有权转移(转移到pair
中的_gameObjects
)。
但是,正如@Xeo在评论中指出的那样,第二种选择违反了最佳实践经验法则:所有权转移应该在所有方面明确。