初始化时不会调用复制/移动构造函数/赋值

时间:2014-09-18 23:18:29

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

A类定义所有复制/移动构造函数/赋值,如下所示:

struct A 
{
    std::string s;

    A() : s("test") { }
    A(const A& other) : s(other.s) { std::cout << "Copy constructor\n";}
    A(A&& other) : s(std::move(other.s)) { std::cout << "Move constructor\n";}
    A& operator= (const A& other) { std::cout << "Copy assignment\n"; s = other.s; return *this;}
    A& operator= (A&& other) { std::cout << "Move assignment\n"; s = std::move(other.s); return *this;}
};

以下是返回A类对象的函数:

A f(A a) { return a; }
A g() { return A(); }

main()功能是:

int main()
{
    A a1 = f(A());          // Move-construct
    A a2 = std::move(a1);   // Move-construct
    A a3 (std::move(a2));   // Move-construct
    A a4 (a1);              // Copy-construct
    A a5 = a4;              // Copy-construct
    a5 = f(A());            // Move constructor + Move assignment
    a5 = a4;                // Copy assignment
    a5 = g();               // Move assignment
    A a6 = g();             // None!! Member-wise assignment (?)
}

任何人都可以告诉我,为什么在a6没有调用构造函数和赋值运算符? C ++ 11的哪些文档描述了这种行为?

2 个答案:

答案 0 :(得分:3)

这称为复制省略,在 C ++标准,第12.8节第31页中有描述。

  

当满足某些条件时,允许省略实现   复制/移动类对象的构造,即使构造函数   选择用于复制/移动操作和/或析构函数   对象有副作用。在这种情况下,实施处理   省略的复制/移动操作的源和目标只是两个   引用同一个对象的不同方式(...)

也描述了这种情况。其中之一是:

  

当一个临时类对象尚未绑定到引用时   将被复制/移动到具有相同cv-unqualified的类对象   类型,通过构造,可以省略复制/移动操作   临时对象直接进入省略的复制/移动目标

当g()返回一个临时匿名对象(未绑定到引用)时,is直接构造到目标a6中。在您的示例中,使用了g&#39的return语句的默认构造函数。

答案 1 :(得分:1)

A a6 = g();中的http://en.wikipedia.org/wiki/Return_value_optimizationg中的代码通过调用a6内部A构造函数创建g { {1}}。