【问题标题】:How many times the constructors are called?构造函数被调用多少次?
【发布时间】:2013-09-05 03:47:45
【问题描述】:

我对 std::move 的东西感到很困惑。假设我有这个 一段代码:

string foo() {
  string t = "xxxx";
  return t;
}

string s = foo();

字符串构造函数被调用了多少次?是2还是3? 编译器会为这一行使用 move 吗?

string s = foo();

如果是这样,在函数中我什至没有返回右值引用,那怎么可能 编译器调用移动构造函数?

【问题讨论】:

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


    【解决方案1】:

    这取决于编译器。在这种情况下,标准要求至少有一个构造函数调用。即t的构造。

    但是该标准允许其他两种可能性:从t 输出foo 的值的移动构造,以及从foo 的值输出的s 的移动构造。大多数体面的编译器会放弃这些构造函数,直接在内存中为s 构造t。这种优化之所以成为可能,是因为如果编译器选择不调用,标准允许不调用这些构造函数。

    这称为复制/移动“省略”。

    如果是这样,在函数中我什至没有返回右值引用,那么编译器如何调用移动构造函数?

    您似乎误以为&& 意味着“移动”,并且如果某处没有&&,那么移动就不会发生。或者移动构造需要move,这也是不正确的。

    C++ 以这样一种方式指定,即某些地方的某些类型的表达式被认为是有效的。这意味着值或引用将在绑定到& 参数之前尝试绑定到&& 参数。例如,临时对象将优先绑定到 && 参数,然后再绑定到 const& 参数。这就是为什么用于构造该类型值的临时对象将被移出。

    如果你有一个函数返回某个类型的值T,并且返回表达式的形式为return x,其中x 是自动存储持续时间的T 类型的命名变量(即: 函数参数或堆栈变量),那么标准要求这个返回表达式move从x构造返回值。

    foo 的返回值是一个临时值。 C++ 的规则要求临时对象在const& 之前绑定到&& 参数。因此,您可以将构造移动到s

    【讨论】:

    • 如果我们假设编译器不做任何优化怎么办?
    • @WhatABeautifulWorld:那么它将是我所说的一个构造函数加上我所说的两个可选构造函数是可选的。
    • 我是否必须更改 foo 的函数定义才能移动它?我在想: string&& foo() {...} 否则编译器怎么知道? String 只是一个例子,实际上我有自己的 obj...
    • @WhatABeautifulWorld NO.永远不要返回右值引用。右值引用是引用,在 C++ 中,您永远不能返回对局部变量 stackoverflow.com/questions/6441218/… 的引用。右值引用仍然是引用;它们并不神奇。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多