c++ - 在没有 move 构造函数或 move 赋值的情况下调用 std::move

标签 c++ c++11 move-semantics

我们知道 std::move does not actually move anything .它只是将左值引用 (&) 转换为右值引用 (&&)。
那么在下面的例子中,拷贝构造函数是如何被调用的呢?如果没有 move 构造函数,构造使用 std::move() 的对象如何回退到复制构造函数?究竟如何绑定(bind)变量 b发生?

struct Test {
  // Default constructor
  Test() {
    std::cout << "Constructor is called." << std::endl;
    mValue = 0;
  }
  
  // Copy constructor
  Test(const Test& rhs) {
    std::cout << "Copy Constructor is called." << std::endl;
    mName = rhs.mName;
    mValue = rhs.mValue;
  }
    
  std::string mName;
  int mValue;
};

int main() {
  Test a;
  Test b = std::move(a);
  return 0;
}
输出:
Constructor is called.
Copy Constructor is called.

最佳答案

让我们以此类推。想想这段代码:

void doSomething(const int& x) {
    std::cout << "You like " << x << "? That's my favorite number!" << std::endl;
}

int main() {
    doSomething(137); // <-- Here
}
现在,专注于 main 中的调用。这段代码编译和运行得很好,但是有点奇怪。请注意, doSomething 接受 const int& 。这意味着它接受对 int 的引用,并且引用(通常)仅绑定(bind)到左值。但是这里的参数 137 是一个右值。是什么赋予了?
这样做的原因是 C++ 语言特别允许 const 左值引用绑定(bind)到右值,即使常规左值引用不能。例如:
const int& totallyLegal = 137; // Yep, that's fine!
int& whoaNotCoolMan     = 42;  // Compile error!
您可以这样做有几个原因。如果你有一个 const 的左值引用,你已经 promise 你可以查看被引用的对象,但你不能修改它。因此,将左值引用绑定(bind)到右值是安全的,因为这样您就没有办法获取“纯值”并为其分配一些东西。从历史上看,在 C++11 之前,当右值引用不存在时,这使得编写函数成为可能,这些函数会说“请以不涉及复制的方式将此参数传递给我”,方法是使用 const左值引用。
现在我们有了左值引用,这条规则引入了一些以前没有的混淆点。特别是, const T& 可以绑定(bind)到 T 类型的任何表达式的结果,即使它是 T&T&& 。这就是在您的情况下选择复制构造函数的原因。
不过,这里还有一个细微差别。就像 C++ 编译器会自动为类定义默认构造函数、复制构造函数和赋值运算符一样,只要您自己不这样做,C++ 编译器也可以自动定义 move 构造函数。但是,有一条规则说,如果一个类型有一个用户定义的复制构造函数,那么编译器不会为你生成一个 move 构造函数。因此,您的问题的完整答案是“复制构造函数的存在意味着没有定义 move 构造函数,并且由于复制构造函数接受 const 左值引用,它将绑定(bind)到右值和左值。”

关于c++ - 在没有 move 构造函数或 move 赋值的情况下调用 std::move,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63852863/

相关文章:

c++ - 不确定如何使用来自另一个类的对象创建带有参数的构造函数

c++ - 原子 bool 变量的一条语句中的多重赋值

C++:删除自定义迭代器上的后增量运算符是否安全?

c++ - unordered_map 的存在决定了是使用复制构造函数还是 move 构造函数

c++ - 应该在构造函数链中使用 move 语义吗?

c++ - Qt QML Desktop 应用程序自动化测试

c++ - 如何将对象转换为int?

c++ - Arduino 不写入 SD 卡?

c++ - 当我添加一个新元素时,Unordered_map 表现得很奇怪

c++ - 使用 move 语义和完美转发实现 'lazy'运算符+