我是C ++ 11中移动语义的新手,而且我不太清楚如何处理unique_ptr
构造函数或函数中的参数。考虑此类本身的引用:
#include <memory>
class Base
{
public:
typedef unique_ptr<Base> UPtr;
Base(){}
Base(Base::UPtr n):next(std::move(n)){}
virtual ~Base(){}
void setNext(Base::UPtr n)
{
next = std::move(n);
}
protected :
Base::UPtr next;
};
这是我应该如何编写带有unique_ptr
参数的函数吗?
我需要std::move
在调用代码中使用吗?
Base::UPtr b1;
Base::UPtr b2(new Base());
b1->setNext(b2); //should I write b1->setNext(std::move(b2)); instead?
以下是将唯一指针作为参数的可能方法及其相关含义。
Base(std::unique_ptr<Base> n)
: next(std::move(n)) {}
为了使用户能够调用它,他们必须执行以下操作之一:
Base newBase(std::move(nextBase));
Base fromTemp(std::unique_ptr<Base>(new Base(...));
按值获取唯一的指针意味着您正在将指针的所有权转让给所涉及的函数/对象/等。后newBase
构造,nextBase
保证是空的。您不拥有该对象,甚至没有指针。它消失了。
这是可以确保的,因为我们按值取参数。std::move
实际上并没有移动任何东西;这只是一个花哨的演员。std::move(nextBase)
返回Base&&
作为r值引用的nextBase
。这就是全部。
因为Base::Base(std::unique_ptr<Base> n)
它的参数是通过值而不是r值引用,所以C ++会自动为我们构造一个临时变量。它通过std::unique_ptr<Base>
从中Base&&
提供了功能,我们通过创建了一个std::move(nextBase)
。正是这个临时结构的构造实际上将值从中nextBase
移到了函数参数中n
。
Base(std::unique_ptr<Base> &n)
: next(std::move(n)) {}
必须在实际的L值(命名变量)上调用它。不能用这样的临时调用:
Base newBase(std::unique_ptr<Base>(new Base)); //Illegal in this case.
其含义与非常量引用的任何其他用法相同:该函数可以声明也可以不声明指针的所有权。给出以下代码:
Base newBase(nextBase);
无法保证nextBase
为空。它可能是空的;可能不会。这实际上取决于Base::Base(std::unique_ptr<Base> &n)
要做什么。因此,仅从函数签名中就不会很明显了。您必须阅读实现(或相关文档)。
因此,我不建议将此作为接口。
Base(std::unique_ptr<Base> const &n);
我没有显示实现,因为您不能从移出const&
。通过传递一个const&
,您表示该函数可以Base
通过指针访问,但不能将其存储在任何地方。它不能要求它的所有权。
这可能很有用。不一定要针对您的特定情况,但是能够给某人一个指针并知道他们不能(没有违反C ++的规则,就像不抛弃一样const
)声称拥有它始终是一件好事。他们无法存储它。他们可以将其传递给其他人,但是其他人必须遵守相同的规则。
Base(std::unique_ptr<Base> &&n)
: next(std::move(n)) {}
这或多或少与“通过非常量l值引用”情况相同。区别是两件事。
您可以通过一个临时的:
Base newBase(std::unique_ptr<Base>(new Base)); //legal now..
您必须使用std::move
通过非暂时性的参数时。
后者确实是问题。如果看到此行:
Base newBase(std::move(nextBase));
您有合理的期望,在此行完成之后,nextBase
应该为空。它应该已经从。毕竟,您已经std::move
坐在那里,告诉您运动已经发生。
问题在于它还没有。不保证已将其移出。它可能已从中移出,但是您只有通过查看源代码才能知道。您不能仅从函数签名中分辨出来。
unique_ptr
,请按价值来接受它。unique_ptr
执行期间使用某个函数,请将该函数取为const&
。或者,将&
或传递给所const&
指向的实际类型,而不是使用unique_ptr
。&&
。但是我强烈建议不要在可能的情况下这样做。您无法复制unique_ptr
。您只能移动它。正确的方法是使用std::move
标准库函数。
如果unique_ptr
按值取值,则可以自由地移动它。但是运动实际上并没有因为std::move
。采取以下声明:
std::unique_ptr<Base> newPtr(std::move(oldPtr));
这实际上是两个声明:
std::unique_ptr<Base> &&temporary = std::move(oldPtr);
std::unique_ptr<Base> newPtr(temporary);
(注意:以上代码在技术上无法编译,因为非临时性r值引用实际上并非r值。此处仅出于演示目的)。
的temporary
仅仅是一个r值参考oldPtr
。它位于运动发生位置的构造函数中newPtr
。unique_ptr
的move构造函数(&&
本身带有a的构造函数)是实际的运动。
如果您有unique_ptr
值,并且想要将其存储在某个位置,则必须使用std::move
该值进行存储。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句