0

在过去的一个小时里一直停留在这段代码上,仍然试图让我的头脑围绕智能指针并实现它们,但这个问题让我很困惑。

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

3 回答 3

3

您需要通过使用将所有权从addEntityto传递:Addstd::move

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

unique_ptr如果不明确允许将其移出,则无法传递 a 。这就是使它成为唯一指针的原因。如果您可以复制它,那么原件和副本都将指向同一个对象。当您离开它时,原始指针将所有权放弃给新指针。

于 2013-04-14T16:25:53.273 回答
1

您正在尝试将unique_ptr 左值传递给采用unique_ptr by value的函数,这将导致创建该指针的副本:这是故意禁止的。唯一指针旨在模拟唯一所有权:这意味着拥有唯一指针的实体拥有指向对象的所有权。

复制一个唯一指针将意味着在整个系统中分布有多个拥有指针:这当然会破坏唯一所有权的目的本身,这解释了为什么您不能复制唯一指针。

你可以做的是转移这个所有权,所以如果你调用一个接受唯一指针的函数,你可以在将它作为参数传递给该函数时移动它:unique_ptr

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

请注意,通过远离唯一指针来转移所有权意味着调用函数留下了一个“僵尸”唯一指针对象,该对象不再拥有它先前指向的对象:因此,调用函数不应尝试取消引用它了。

于 2013-04-14T16:27:23.013 回答
1

您不能通过unique_ptr值传递。以下正在尝试创建 a 的副本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>which 的输入参数,GameObjectManager::Add一个是std::pairin的输入参数_gameObjects

另一种解决方案是修改签名GameObjectManager::Add以获取参考:

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

现在,您可以像当前一样调用该方法,这将只导致一次所有权转移(到pairin _gameObjects)。

但是,正如@Xeo 在评论中指出的那样,第二个选项违反了最佳实践的经验法则,即:所有权转让应该在所有点上都是明确的

于 2013-04-14T16:34:42.980 回答