【问题标题】:How copy constructor can be called with rvalue如何使用右值调用复制构造函数
【发布时间】:2018-07-04 05:07:49
【问题描述】:

MWE:

struct A {
    A() {std::cout << "constructor" << std::endl; }
    A(const A& a) {std::cout << "copy constructor" << std::endl; }
    A(A&& a) {std::cout << "move constructor" << std::endl; }
};

int main() {
    A a1{};
    A a2{ a1 };
    A a3{ A{} };
    A a4{ std::move(a3) };
    return 0;
}

输出:

constructor
copy constructor
constructor
move constructor

fora2 使用了复制省略,这是对编译器的优化,一切似乎都很好。但是,当我注释掉移动构造函数时,会调用复制构造函数来代替移动构造函数。如何将右值转换为 const 左值引用? 输出:

constructor
copy constructor
constructor
copy constructor

程序编译在VS2017

【问题讨论】:

  • “如何将右值转换为 const 左值引用?” 很容易。无时无刻不在发生。为什么你认为这会是个问题?好吧,“转换”可能是一个错误的术语:一个 const 左值引用可以绑定到一个临时对象。
  • @IgorTandetnik,是的,你是对的。这一切都是由于const 而发生的,以前不知道这一点。正如您在答案中提到的那样,也许您可​​以详细说明bounding。它是如何工作的?
  • “如何将右值转换为 const 左值引用?” 这不是通过复制优化的基础吗?
  • @Jean-BaptisteYunès 什么是“逐个复制优化”?
  • @curiousguy 将 f(T v) 替换为 f(const T &amp;v) 以消除每次调用时的副本。

标签: c++11 copy-constructor move-semantics move-constructor copy-elision


【解决方案1】:

来自 en.cppreference.com:

如果同时提供了复制和移动构造函数并且没有其他构造函数 构造函数是可行的,重载决议选择移动 如果参数是相同类型的右值(一个 xvalue 例如 std::move 或纯右值(例如无名)的结果 临时(C++17 前)),并选择复制构造函数,如果 参数是一个左值(命名对象或返回的函数/运算符 左值参考)。如果只提供了复制构造函数,则所有 参数类别选择它(只要它引用 const,因为右值可以绑定到 const 引用),这使得 当移动不可用时,复制移动的后备。

这清楚地表明右值可以绑定到 const 左值引用。

【讨论】:

  • 复制是后备。如果复制和移动都可用怎么办? move 是否仅用于(从 17 开始)显式移动?我可以确认无名临时人员是通过其他方式处理的,但我无法生成打印消息来准确告诉我是什么。
猜你喜欢
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多