传递std :: unique_ptr的问题

时间:2013-04-14 16:22:28

标签: c++ c++11

过去一小时一直坚持使用这段代码,仍然试图了解智能指针并实现它们,但这个问题让我感到很难过。

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>'  

3 个答案:

答案 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在评论中指出的那样,第二种选择违反了最佳实践经验法则:所有权转移应该在所有方面明确