C++ 问题传递标准::唯一的ptr';s

C++ 问题传递标准::唯一的ptr';s,c++,c++11,C++,C++11,在过去的一个小时里,我一直在研究这段代码,仍然在试图了解智能指针并实现它们,但这个问题已经困扰了我相当长一段时间 void GameState::addEntity(std::unique_ptr<Entity> gameObject) { if(gameObject->isCollidable()){ _actors.Add(gameObject); } else { _props.Add(gameObject); }

在过去的一个小时里,我一直在研究这段代码,仍然在试图了解智能指针并实现它们,但这个问题已经困扰了我相当长一段时间

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++;
}
void GameState::addEntity(std::unique_ptr gameObject)
{
如果(gameObject->isCollidable()){
_添加(游戏对象);
}否则{
_道具添加(游戏对象);
}
}
//这是上述函数试图调用的方法。
void GameObjectManager::Add(std::unique_ptr gameObject)
{
_插入(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::unique\u ptr::unique\u ptr”:无法访问在类“std::unique\u ptr”中声明的私有成员

您需要使用
std::move
将所有权从
addEntity
传递到
Add

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

如果不明确允许从中移动
唯一\u ptr
,则无法传递它。这就是它成为唯一指针的原因。如果可以复制,则原始对象和副本都将指向同一对象。当您从它移动时,原始指针将所有权放弃给新指针。

您需要使用
std::move
将所有权从
addEntity
传递到
Add

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

如果不明确允许从中移动
唯一\u ptr
,则无法传递它。这就是它成为唯一指针的原因。如果可以复制,则原始对象和副本都将指向同一对象。当您离开它时,原始指针放弃了对新指针的所有权。

您试图将
唯一\u ptr
左值传递给一个按值获取
唯一\u ptr
的函数,这将导致创建该指针的副本:这是故意禁止的。唯一指针用于建模唯一所有权:这意味着持有唯一指针的实体拥有指向对象的所有权

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

您可以做的是转移此所有权,因此如果调用接受唯一指针的函数,则可以在将其作为参数传递给该函数时移动
unique\u ptr

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

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

您试图将
唯一\u ptr
左值传递给按值获取
唯一\u ptr
的函数,这将导致创建该指针的副本:这是故意禁止的。唯一指针用于建模唯一所有权:这意味着持有唯一指针的实体拥有指向对象的所有权

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

您可以做的是转移此所有权,因此如果调用接受唯一指针的函数,则可以在将其作为参数传递给该函数时移动
unique\u ptr

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

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

不能通过值传递
唯一\u ptr
。以下用户正在尝试创建禁止的
唯一\u ptr
副本:

if(gameObject->isCollidable()){
    _actors.Add(gameObject);     // THIS LINE
} else {
    _props.Add(gameObject);      // and THIS LINE
}
正在通过
std::move()
传递解决方案:

这将导致两次所有权转让。一个到
std::unique\u ptr
,这是
GameObjectManager::Add
的输入参数,另一个到
\u gameObjects
中的
std::pair

另一个解决方案是修改
GameObjectManager::Add
的签名以获取引用:

void GameObjectManager::Add(std::unique_ptr<Entity> & gameObject)
//                                                 ^^^
void GameObjectManager::Add(std::unique_ptr&gameObject)
//                                                 ^^^
现在,您可以像当前一样调用该方法,这将只导致一次所有权转移(到
\u gameObjects
中的


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

您不能通过值传递
唯一的\u ptr
。以下用户正在尝试创建禁止的
唯一\u ptr
副本:

if(gameObject->isCollidable()){
    _actors.Add(gameObject);     // THIS LINE
} else {
    _props.Add(gameObject);      // and THIS LINE
}
正在通过
std::move()
传递解决方案:

这将导致两次所有权转让。一个到
std::unique\u ptr
,这是
GameObjectManager::Add
的输入参数,另一个到
\u gameObjects
中的
std::pair

另一个解决方案是修改
GameObjectManager::Add
的签名以获取引用:

void GameObjectManager::Add(std::unique_ptr<Entity> & gameObject)
//                                                 ^^^
void GameObjectManager::Add(std::unique_ptr&gameObject)
//                                                 ^^^
现在,您可以像当前一样调用该方法,这将只导致一次所有权转移(到
\u gameObjects
中的


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

如果您明确允许将其移出,它就不再是副本了:哦,太棒了!谢谢你的修复!如果你