gpt4 book ai didi

c++ - 显式复制构造函数和统一初始化

转载 作者:IT老高 更新时间:2023-10-28 12:57:54 27 4
gpt4 key购买 nike

显式复制构造函数不允许 Foo foo = bar; 之类的东西,并将复制用法强制为 Foo foo(bar);。此外,显式复制构造函数也不允许从函数中按值返回对象。但是,我尝试用大括号替换复制初始化,就像这样

struct Foo
{
Foo() = default;
explicit Foo(const Foo&) = default;
};

int main()
{
Foo bar;
Foo foo{bar}; // error here
}

我得到了错误 (g++5.2)

error: no matching function for call to 'Foo::Foo(Foo&)'

或 (clang++)

error: excess elements in struct initializer

删除 explicit 使代码在 g++ 下可编译,clang++ 仍然失败并出现同样的错误(感谢@Steephen)。这里发生了什么?统一初始化是否被视为初始化列表构造函数(胜过所有其他构造函数)?但是如果是这样的话,为什么在拷贝构造函数不显式的情况下程序会编译呢?

最佳答案

您遇到了 Core issue 1467 的决议解决的案例在 C++14 完成后立即完成。

让我们首先注意类 foo 是一个聚合。您的代码正在为 foo 执行 direct-list-initialization。列表初始化的规则在 [8.5.4p3] 中。

在 C++14 中(引自 N4140,最接近已发布标准的工作草案),上面的段落以:

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1).

[...]

因此,如果您的类是聚合类,编译器会尝试进行聚合初始化,但失败了。

这被认为是一个问题,并在工作草案中得到了解决。引用当前版本 N4527,上述段落现在以:

List-initialization of an object or reference of type T is defined as follows:

  • If T is a class type and the initializer list has a single element of type cv U, where U is T or a class derived from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
  • Otherwise, if T is a character array and the initializer list has a single element that is an appropriately typed string literal (8.5.2), initialization is performed as described in that section.
  • Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).

[...]

您的示例现在属于第一个项目符号所描述的情况,并且 foodirect-list-initialized 使用默认的复制构造函数(无论它是否是 explicit,因为它是直接初始化)。

也就是说……如果编译器实现了缺陷报告中的解决方案。

  • GCC 5.2.0(和 6.0.0 主干)似乎可以这样做,但似乎有一个与该 explicit 相关的错误。
  • Clang 3.6.0 没有,但 3.8.0 trunk 可以,而且正确(explicit 无关紧要)。
  • MSVC 14 有,但 IDE 中的 IntelliSense 没有(bar 下的波浪线 - 看起来 IntelliSense 使用的 EDG 编译器也没有更新)。

更新:自编写此答案以来,工作草案已通过与问题中的示例和上述解释相关的几种方式进行了进一步修改:

  • CWG 2137表示上面引用的段落中的第一个项目符号将该异常应用于所有类类型(问题说明包含相关示例)有点过分。现在子弹的开头是:
    • If T is an aggregate class and [...]
  • CWG 1518 的分辨率包含在纸上P0398R0表示声明 explicit 构造函数(甚至默认)的类不再是聚合。

这并没有改变这样一个事实,即在实现所有更改之后,问题中的示例旨在工作,无论是否使用 explicit;值得知道的是,使它工作的底层机制发生了轻微的变化。

请注意,所有这些更改都是缺陷报告的解决方案,因此它们应该在编译器处于 C++14 和 C++11 模式时也适用。

关于c++ - 显式复制构造函数和统一初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31776359/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com