Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the copy-constructor not called when returning by-value a list-initialized object?

Tags:

c++

c++11

I understand that when objects are returned by-value from a function, their copy-constructors are called. If a class has a deleted copy-constructor, returning by value will fail.

struct X {
    X(const X &) = delete;
};

X f() {
   return X{};
}

error: call to deleted constructor of 'X'

C++11 gives us extended-initializers. And I read somewhere on a SO post that this

X f() {
    return {};
}

is the same as

X f() {
    return X{};
}

So why doesn't the below code give me an error? It passes and I even get to call the function in main:

struct D {
   D(const D &) = delete;
};

D f() { return {}; }

int main()
{
   f();
}

Here is a demo. No error is reported. I find that weird because I believe that the copy-constructor should be called. Can anyone explain why no error is given?

like image 624
template boy Avatar asked Mar 10 '13 22:03

template boy


1 Answers

And I read somewhere on a SO post that this [...] is the same as [...]

They were wrong. They're similar, but not the same.

By using the braced-init-list, you are able to initialize the return value in-place. If you create a temporary, then what you're doing is creating the temporary and then copying it into the return value. Any compiler worth its salt will elide it, but the copy constructor still must be accessible.

But since the braced-init-list initializes the return value in-place, you don't need access to the copy constructor.

From the standard, section 6.6.3, p2:

A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.

Note that "copy-list-initialization" is not similar to "copy-initialization"; it doesn't do any copying and therefore it doesn't require an accessible copy constructor. The only difference between "copy-list-initialization" and "direct-list-initialization" is that the former will choke on explicit constructors.

like image 78
Nicol Bolas Avatar answered Sep 20 '22 10:09

Nicol Bolas