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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With