调用复制构造函数时会发生什么类型的初始化?

What Type of Initialization Occurs When Calling Copy Constructor?

考虑下面的简单结构(默认只是显式的)。

struct foo {
    foo() = default;
    foo(const foo&) = default;
};

foo bar() {
    return foo{}; // return does copy init
}

下面进行了什么样的初始化?

foo a;        // default init
foo b{};      // value initialization
foo c{bar()}; // ?? mandatory copy elision. is this considered direct init? so copy init to return from 
              // bar(), then direct init to init c?
foo d{c};     // ?? copy constructor called. is this considered direct init or copy init?
foo e = d;    // copy init

正在寻找 C++ 17 的答案。请在适用时提供参考。 谢谢

给定 foo c{bar()};cdirect-list-initialized 来自 bar() 的 return 值。 foo d{c};也是一样,d是从c直接列表初始化的。

  1. initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)

作为结果,对于 foo c{bar()};,由于 mandatory copy elision (C++17 起) return 语句中的复制构造和 c 的初始化省略,c直接由默认构造函数构造。对于foo d{c};,选择复制构造函数构造d.

顺便说一句:在 bar() 中,return foo{}; 执行 copy initialization, because of mandatory copy elision (since C++17) the copy construction is omitted, the return value is initialized by the default constructor directly (since C++20). (Until C++20 it'll be aggregate-initialized。)

What Type of Initialization Occurs When Calling Copy Constructor?

你的问题是倒退的,最终无法回答。

初始化形式决定了用于获取初始化表达式并从中初始化对象的各种步骤。有多种形式的初始化,其中大多数都有某种机制最终可以导致复制构造函数调用。列表初始化、直接初始化、复制初始化、聚合初始化,所有这些都可以调用复制构造函数,当然,给定正确的初始化程序。

因此,您无法仅仅从调用复制构造函数的事实中知道使用了哪种初始化形式。

所使用的初始化形式由初始化对象的语法决定。

foo c{bar()};
foo d{c};

它们使用相同的初始化语法,因此它们使用相同的初始化形式。这是直接初始化,但是因为初始化器是花括号初始化列表 ({}),所以很快就会变成直接列表初始化。

foo e = d;

此语法调用复制初始化。