为了账号安全,请及时绑定邮箱和手机立即绑定

如何将唯一_PTR参数传递给构造函数或函数?

如何将唯一_PTR参数传递给构造函数或函数?

C++
慕无忌1623718 2019-07-03 11:02:22
如何将唯一_PTR参数传递给构造函数或函数?我刚开始在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?
查看完整描述

3 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

以下是将唯一指针作为参数的可能方法,以及它们的相关含义。

(A)按价值计算

Base(std::unique_ptr<Base> n)
  : next(std::move(n)) {}

为了让用户调用它,他们必须执行以下操作之一:

Base newBase(std::move(nextBase));Base fromTemp(std::unique_ptr<Base>(new Base(...));

通过值获取唯一指针意味着转移指向有关函数/对象/etc的指针的所有权。后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.

(B)非Const l值参考

Base(std::unique_ptr<Base> &n)
  : next(std::move(n)) {}

这必须在实际的l-值(一个命名变量)上调用。不能用这样的临时方式调用它:

Base newBase(std::unique_ptr<Base>(new Base)); //Illegal in this case.

它的含义与任何其他非const引用的含义相同:函数可以也可能不会声明指针的所有权。鉴于此代码:

Base newBase(nextBase);

不能保证nextBase是空的。它可以,可能是空的;它可能不是。这真的取决于什么Base::Base(std::unique_ptr<Base> &n)想做什么。因此,仅仅从函数签名中可以看出将要发生的事情并不是很明显;您必须阅读实现(或相关的文档)。

因此,我不建议把它作为一个接口。

(C)由Const l-

Base(std::unique_ptr<Base> const &n);

我没有显示一个实现,因为你不可能从一个const&..通过一个const&,您是说函数可以访问Base通过指针,但它不能商店任何地方。它不能声称拥有它的所有权。

这可能很有用。不一定适合你的具体情况,但总能给某人一个指针,并且知道他们不可能(不违反C+的规则,就像没有抛弃const)声称拥有它的所有权。他们不能储存。他们可以把它传给别人,但其他人必须遵守同样的规则。

(D)按r-

Base(std::unique_ptr<Base> &&n)
  : next(std::move(n)) {}

这与“非Const l-value Reference”的情况大致相同。区别是两件事。

  1. 你,你们能,会,可以临时通过:

    Base newBase(std::unique_ptr<Base>(new Base)); //legal now..
  2. 你,你们使用std::move在传递非临时参数时。

后者才是真正的问题。如果你看到这一行:

Base newBase(std::move(nextBase));

你有一个合理的期望,在这一行完成之后,nextBase应该是空的。它应该被移开的。毕竟,你有std::move坐在那里告诉你运动已经发生了。

问题是它没有。它不是被移出。它可以,可能已被移除,但您只能通过查看源代码才能知道。您不能只从函数签名中分辨出来。

建议

  • (A)按价值计算:

    如果你想让一个函数声称

    所有权

    一种

    unique_ptr

    用价值来衡量。
  • (C)Const l-参考价值:

    如果您的意思是让一个函数简单地使用

    unique_ptr

    在该函数执行期间,请按

    const&

    ..或者,传递一个

    &

    const&

    指向的实际类型,而不是使用

    unique_ptr.

  • (D)按r值计算:

    如果一个函数可以或不声明所有权(取决于内部代码路径),那么请通过

    &&

    ..但我强烈建议不要在可能的情况下这样做。

如何操作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的移动构造函数(接受&&对自己来说)是什么实际的运动。

如果你有unique_ptr如果你想把它藏在某个地方,你使用std::move去做储藏室。


查看完整回答
反对 回复 2019-07-03
?
ITMISS

TA贡献1871条经验 获得超8个赞

是的,如果你拿了unique_ptr构造函数中的值。解释是件好事。自unique_ptr不可复制(私有副本ctor),您所写的应该会给您一个编译器错误。


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 376 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信