Reputation: 105
Consider the simple struct below (defaulted just to be explicit).
struct foo {
foo() = default;
foo(const foo&) = default;
};
foo bar() {
return foo{}; // return does copy init
}
What kind of initializations take place below?
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
Looking for answers for C++ 17. Please provide references whenever applicable. Thanks.
Upvotes: 1
Views: 196
Reputation: 172934
Given foo c{bar()};
, c
is direct-list-initialized from the return value of bar()
. And it's same for foo d{c};
, d
is direct-list-initialized from c
.
- 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)
As the effect, for foo c{bar()};
, because of mandatory copy elision (since C++17) the copy construction in the return
statement and the initialization of c
are omitted, c
is constructed by the default constructor directly. For foo d{c};
, the copy constructor is selected to construct d
.
BTW: In bar()
, return foo{};
performs 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.)
Upvotes: 4
Reputation: 473537
What Type of Initialization Occurs When Calling Copy Constructor?
Your question is backwards and ultimately unanswerable.
Initialization forms determine the various steps used to take the initializer expressions and initialize an object from them. There are many forms of initialization, and most of them have some mechanism that can ultimately lead to a copy constructor call. List initialization, direct initialization, copy initialization, aggregate initialization, all of these could call the copy constructor, given the right initializer, of course.
As such, you cannot know which initialization form was used solely from the fact that a copy constructor was called.
The form of initialization used is determined by the syntax that initializes the object.
foo c{bar()};
foo d{c};
These use the same initialization syntax, so they use the same form of initialization. This is direct-initialization, but because the initializer is a braced-init-list ({}
), that will quickly become direct-list-initialization.
foo e = d;
This syntax invokes copy initialization.
Upvotes: 0