类构造函数匹配,为什么没有在这里调用移动构造函数?

时间:2018-02-13 08:31:38

标签: c++

我最近在学习移动构造函数,我遇到了一个奇怪的问题。 我有以下代码:

sap.m.table

输出结果为:

#include <iostream>

class a
{
public:
    a() { printf("default\n"); }
    a(const a& aa) { printf("const lr\n"); }
    a(a& aa) { printf("lr\n"); }
    a(a&& aa) { printf("rr\n"); }
    a(const a&& aa) { printf("const rr\n"); }
};

a foo()
{
    return a();
}

void func(a& a) {
    printf("func lr\n");
}

void func(a&& aa) {
    printf("func rr\n");
}

int main()
{
    printf("a1: ");a a1;
    printf("a2: ");a a2(a1);
    printf("a3: ");a a3(std::move(a2));
    printf("a4: ");a a4(foo());
    printf("a5: ");a a5(std::move(foo()));

    func(foo());
}
除了a4之外,一切都很好。我希望a1: default a2: lr a3: rr a4: default a5: default rr default func rr 的返回类型是一个右值。我认为foo()的呼吁最终证明了这一点。那么为什么在构造a4时没有调用移动构造函数呢?同时,在构建a5时会调用它。

1 个答案:

答案 0 :(得分:6)

这可能是因为copy_elision

  

在下列情况下,编制者需要省略   类对象的复制和移动构造:

     
      
  1. 在初始化中,如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象:
  2.         

    T x = T(T(T())); // only one call to default constructor of T, to initialize x

         
        
    1. 在函数调用中,如果return语句的操作数是prvalue,并且函数的返回类型与该prvalue的类型相同:

      T f() { return T{}; }
      T x = f();         // only one call to default constructor of T, to initialize x
      T* p = new T(f()); // only one call to default constructor of T, to initialize *p
      
    2.   

你的情况属于第二种情况。