【问题标题】:Moving lvalue reference into member variable将左值引用移动到成员变量中
【发布时间】:2018-06-11 14:34:04
【问题描述】:

假设你有这个简单的类:

class GenericClass {
public:
    GenericClass(std::unique_ptr<uint8_t[]>& lref) {
    this->var = std::move(lref);
}

private:
    std::unique_ptr<uint8_t[]> var;
}

ctor 究竟是如何处理“移动”的? 引用指向的左值的所有权是转移到成员变量还是引用另一个左值?

【问题讨论】:

  • 参数实际上应该是一个右值引用,以明确构造函数从它移动,并且如果传递了左值,则需要从调用方显式移动。
  • 不是我会批评,但坦率地说,this-&gt;var = std::move(lref); 作为演员的身体来自恐怖电影。
  • std::move 只不过是一个演员表。

标签: c++ c++11 move move-semantics rvalue-reference


【解决方案1】:

嗯,std::move的效果可以通过一个例子来理解:

std::unique_ptr<uint8_t[]> data = ... ;

assert(data != nullptr);  //data is not nullptr

GenericClass obj(data); //the resource is transferred

assert(data == nullptr); //data must be nullptr

希望 cmets 解释到底发生了什么。

但是,没有cmets,资源从data转移到obj不是很清楚,因为构造函数的设计不够好。所以我建议说清楚:

GenericClass(std::unique_ptr<uint8_t[]>&& lref) //note &&
  : var(std::move(lref)) //use mem-initialize-list
{
}

现在客户端应该改为这样写:

GenericClass obj(std::move(data));

现在即使没有 cmets,客户端代码也是可以理解的。

【讨论】:

  • 是否需要使用:var(std::move(lref))?它已经是一个右值引用,或者至少参数是。
  • @Zebrafish:是的。 std::move 在那里是必需的,因为 lref 仍然是一个左值,尽管它绑定到一个右值。
  • @Zebrafish,值类别与类型正交。它是对unique_ptr&lt;uint8_t[]&gt; 的右值引用类型的左值。
  • “所以我建议让它明确” - 好主意,单参数构造函数可能应该标记为explicit - 不是你在说什么,而是仍然。 ;-)
  • @JesperJuhl:在不知道类的用法的情况下,是的,标记单参数构造函数explicit 通常是个好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
  • 2013-01-29
  • 2018-05-25
相关资源
最近更新 更多