C++中的对象初始化语法(T obj={..}vs T obj{..})



初始化的两种形式T obj = {…}T obj{…}之间有什么区别
我最初认为T obj = {…}T obj = T{…}的简写,其中一个临时对象被复制到我们的新对象中。这虽然不执行复制构造函数(复制省略),但需要它的存在和对它的访问。但当我通过将构造函数设为私有来阻止复制构造函数在这个特定类中的访问时,没有出现错误
这意味着不涉及复制机制。那么"="符号的作用是什么呢
我提到了以下问题,但由于没有解释而感到不满意:
C++11统一初始化是否取代了旧式语法?

编辑:同样,int arr[]{…}int arr[] = {…}之间有区别吗?我问这个问题是为了看看我是否可以在统一初始化和列表初始化之间进行对比。

这些具有几乎完全相同的效果:

  • T x = { 1, 2, 3 };
  • T x { 1, 2, 3 };

从技术上讲,带有=的版本被称为复制列表初始化,另一个版本是直接列表初始化,但这两种形式的行为都由列表初始化行为指定。

区别在于:

  • 如果复制列表初始化选择了explicit构造函数,则代码格式错误
  • 如果Tauto,则:
    • 复制列表初始化推导std::initializer_list<Type_of_element>
    • 直接列表初始化只允许列表中的单个元素,并推导出Type_of_element

更多信息:为什么标准区分直接列表初始化和复制列表初始化?


如果T是一个数组类型,则上述内容仍然适用;由于数组列表初始化总是聚合初始化,因此从来没有选择构造函数,因此这两个版本在所有情况下都是相同的。


T obj = T{...}(不包括auto)与T obj{...}完全相同,因为C++17,即obj直接列表初始化。在C++17之前,存在临时的直接列表初始化,然后从临时复制obj的初始化。

我认为比较这两种语法不是真正的问题。

在我看来,你期望C++17省略的行为与前C++17";优化";该标准允许并且由许多实现来执行。

在该";"优化";,尽管复制构造函数调用可以被省略,但它必须是有效的和可访问的。

C++17省略的情况并非如此

这是一个真正的省略,即仅仅编写T{}并不能真正创建T,而是说";我想要一个CCD_ 23〃;,而实际的临时是";材料化";只有在需要的时候。

这一事实的多余话语实际上被压缩成了一个,所以尽管尖叫着";我想要T!我想要一辆T!我想要一辆T!我想要一辆T"孩子最终仍然只得到一个CCD_ 28。

因此,在C++17中,T obj = T{...}在字面上等同于T obj{...}

这就解释了你所看到的结果,以及你的困惑。


您可以在cppreference.com上阅读有关此功能的更多信息;这是页面顶部的一个片段:

强制省略复制/移动操作

在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数有明显的副作用。对象被直接构造到存储中,否则它们将被复制/移动到存储中。复制/移动构造函数不需要存在或可访问:

  • [..]
  • 在对象的初始化中,当初始化器表达式是与变量类型[..]相同的类类型(忽略cv限定)的prvalue时

最新更新