如何将unique_ptr参数传递给构造函数或函数?

codablank1

我是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?
尼科尔·波拉斯(Nicol Bolas)

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

(A)按价值

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

(B)通过非常量L值引用

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)要做什么。因此,仅从函数签名中就不会很明显了。您必须阅读实现(或相关文档)。

因此,我不建议将此作为接口。

(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)) {}

这或多或少与“通过非常量l值引用”情况相同。区别是两件事。

  1. 可以通过一个临时的:

    Base newBase(std::unique_ptr<Base>(new Base)); //legal now..
    
  2. 必须使用std::move通过非暂时性的参数时。

后者确实是问题。如果看到此行:

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

您有合理的期望,在此行完成之后,nextBase应该为空。它应该已经从。毕竟,您已经std::move坐在那里,告诉您运动已经发生。

问题在于它还没有。保证已将其移出。可能已从中移出,但是您只有通过查看源代码才能知道。您不能仅从函数签名中分辨出来。

推荐建议

  • (A)按价值:如果您要让一个函数声明对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它位于运动发生位置的构造函数newPtrunique_ptr的move构造函数(&&本身带有a的构造函数)是实际的运动。

如果您有unique_ptr值,并且想要将其存储在某个位置,则必须使用std::move该值进行存储。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将std :: unique_ptr传递给函数

如何将NULL或nullptr传递给接收unique_ptr参数的函数?

如何将包含 std::unique_ptr 的 std::optional 结构传递给函数?

如何将字段构造函数参数传递给函数?

将std :: unique_ptr传递给构造函数以获取所有权

如何将参数传递给canActivate的构造函数?

如何将参数传递给静态类构造函数?

笑话:如何将参数传递给模拟构造函数?

如何将固定参数传递给基本构造函数

C ++:将诸如unique_ptr :: get()之类的参数传递给函数是否安全?

将引用参数传递给采用 unique_ptr 的通用引用的函数

传递给函数后如何使用unique_ptr?

如何将 unique_ptr 对象作为参数传递给作为库的类

将unique_ptr <Derived>&传递给接受unique_ptr <Base>&的函数

如何将构造函数传递给构造函数?

如何将参数传递给函数?

如何将非静态成员函数作为unique_ptr删除器传递

如何将函数作为参数传递给transform()函数?

如何将参数从函数传递给其他函数

如何将参数传递给 oop PHP 中的父构造函数?

使用IoC容器时如何将参数传递给构造函数?

如何将参数传递给构造函数反序列化json

如何将参数从控制器传递给FormType构造函数

使用`<fx:include>`时如何将参数传递给控制器的构造函数?

如何将参数传递给Java中的可注入构造函数?

在构造函数中反应绑定,如何将参数传递给道具

如何将构造函数参数传递给 ECMAScript 6 中的导入类?

如何将类型参数传递给泛型类构造函数引用?

如何将视图构造函数参数传递给视图模型