复制构造函数被调用了多少次?



假设我有一个带有复制、移动构造函数、默认构造函数的类node

Node func (Node n){
return n;
}
Node newN = func(Node{});            //#2

那么这些叫了多少次呢?

移动构造器:在#2处一次。

复制构造函数呢?

最多一个建筑和一个移动建筑。

#include <iostream>
using std::cout;
using std::endl;
class Something {
public:
Something() {
cout << __PRETTY_FUNCTION__ << endl;
}
Something(Something&&) {
cout << __PRETTY_FUNCTION__ << endl;
}
Something(const Something&) {
cout << __PRETTY_FUNCTION__ << endl;
}
};
Something foo(Something in) {
return in;
}
int main() {
Something something = foo(Something{});
(void) something;
}

上面的输出是这样的

Something::Something()
Something::Something(Something &&)

Something对象的构造会产生一个 prvalue,它是 RVO 的候选者,这将省略到foo()的函数参数中。 如果使用 C++17 编译,无论如何都会省略此操作,但是当您使用 C++11 和 C++14 编译时,仅当-fno-elide-constructors编译标志不允许

省略时,才会省略此操作。但是,当您从函数返回该对象时,标准不允许发生 NRVO。 明确禁止省略函数参数(有关标准的确切引用,请参见下文)。 所以发生了移动(假设你有一个移动构造函数,如果你没有移动构造函数,那么就会发生一个复制)

因此,总共允许使用省略号,您有一个构造和一个移动构造(如果未定义移动构造函数,则您将获得一个副本)


§ 15.8.3 复制/移动省略 [class.copy.elision]

  1. 当满足某些条件时,允许实现省略类对象的复制/移动构造,...

    • 在具有类返回类型的函数的return语句中,当表达式是与函数返回类型相同(忽略 CV-QUAL)的非易失性自动对象(函数参数或处理程序异常声明(18.3) 引入的变量除外)的名称时,可以通过将自动对象直接构造到函数调用的返回对象中来省略复制/移动操作

如您所见,该语言不允许从函数参数中省略,因此会发生移动。

另请注意,如果显式删除移动构造函数,则此代码将无法编译

最新更新