调用复制构造函数的次数是多少?

时间:2017-06-22 03:18:46

标签: c++ oop

假设我有一个带有副本,移动构造函数,默认构造函数

的类node
Node func (Node n){
  return n;
}

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

然后这些被叫多少次?

移动constuctor:一次在#2。

复制构造函数怎么样?

1 个答案:

答案 0 :(得分:3)

最好是一个建筑和一个移动建筑。

#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编译标志禁止使用elisions时,才会省略此操作。

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

所以总共允许你有一个构造和一个移动构造(如果没有定义移动构造函数,那么你得到一个副本)

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

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

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

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

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