简体   繁体   English

为什么在按值返回列表初始化对象时不调用copy-constructor?

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

I understand that when objects are returned by-value from a function, their copy-constructors are called. 据我所知,当从函数返回-value对象时,会调用它们的copy-constructors。 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. C ++ 11为我们提供了扩展初始化器。 And I read somewhere on a SO post that this 我在SO帖子的某个地方读到了这个

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: 它通过了,我甚至可以在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. 我发现这很奇怪,因为我认为应该调用copy-constructor。 Can anyone explain why no error is given? 任何人都可以解释为什么没有给出错误?

And I read somewhere on a SO post that this [...] is the same as [...] 我在SO帖子上的某个地方读到这个[...]与[...]相同

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 . 通过使用braced-init-list,您可以就地初始化返回值。 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. 但由于braced-init-list就地初始化返回值,因此您不需要访问复制构造函数。

From the standard, section 6.6.3, p2: 从标准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. 带有braced-init-list的return语句通过copy-list-initialization(8.5.4)从指定的初始化列表初始化要从函数返回的对象或引用。

Note that "copy-list-initialization" is not similar to "copy-initialization"; 注意,“copy-list-initialization”与“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. “复制列表初始化”和“直接列表初始化”之间的唯一区别是前者会阻塞explicit构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当按值传递右值到函数时,为什么不调用复制构造函数 - Why isn't the copy-constructor called when passing rvalue by value to function 为什么在这种情况下不调用复制构造函数? - Why is copy-constructor not called in this case? 为什么在调用复制构造函数之前先调用构造函数? - Why Constructor is called before the copy-constructor is called? 如何最小化列表构造函数(复制构造函数)的调用次数? - How to minimize the times that list constructor (either copy-constructor ) is called? 将临时返回对象分配给引用时,为什么需要公共副本构造函数? - Why is a public copy-constructor required when assigning the temporary return object to a reference? 为什么在返回时调用复制构造函数而不是移动构造函数? - Why is the copy constructor called instead of the move constructor when returning? 为什么在程序中调用此复制构造函数? - Why this copy-constructor is invoked in the program? NRV(命名返回值)复制构造函数 - NRV(named return value) copy-constructor 为什么复制构造函数参数为const? - Why is the copy-constructor argument const? 从按值构造函数参数初始化的引用成员 - Reference member initialized from a by-value constructor parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM