【问题标题】:What is the difference between C c(3); and C c{3}; when instantiating a class?C c(3); 有什么区别?和 C c{3};实例化一个类时?
【发布时间】:2017-11-03 01:30:10
【问题描述】:
#include <iostream>

using namespace std;

class C{
    public: int a;
    public: C (int i){a = i ; }

};
int main()
{
    C c(3); // C c{3};
    cout<<c.a;
    return 0;
}

C c(3);C c{3}; 有什么区别?它们的工作方式似乎与调用构造函数相同。

【问题讨论】:

  • 我很惊讶没有一个规范的副本...

标签: c++ initialization


【解决方案1】:

有两个区别:

  1. 大括号初始化语法(假设列表非空)可以调用std::initializer_list&lt;T&gt; 构造函数,并且如果可能,将始终这样做。括号语法不会调用std::initializer_list&lt;T&gt; 构造函数。

  2. 大括号初始化语法禁止缩小转换。

在您的示例中没有区别,但是:

  1. 如果C 有一个采用std::initializer_list&lt;int&gt; 的构造函数,那么C{3} 将调用该构造函数,而C(3) 将调用采用int 的构造函数。

  2. C{3.14} 不会编译,因为转换正在缩小,但C(3.14) 会。

【讨论】:

  • 谢谢。请问C c(3)C c{3}哪一种风格在OO的其他语言中更流行? Java 和 C# 两者都没有,这对吗?
  • C# 和 Java 的构造函数与 C(int i) 几乎相同,只是需要注意的是它们会检查传入的类型。new C(3.14) 将无法编译。但是,不支持 {} 语法。在 C# 中,new C { a = 3 } 是一个对象初始化器,您必须在 {} 中分配成员变量。
  • 您的第一个陈述 1 通常是不正确的:聚合初始化是最高优先级;然后对空列表进行值初始化。然后是C 本身就是std::initializer_list 的情况。只有这样,构造函数才会被考虑,此时重载解析有机会匹配接受 std::initializer_listC 的构造函数。无论如何,从 C++14 开始——列表初始化规范中的事物顺序似乎随着每个新的标准草案而跳跃
  • @M.M 关于空列表的好点,我会更新我的答案以反映这一点。我不认为聚合初始化与我写的内容冲突,因为一个类不能既是聚合又具有std::initializer_list 构造函数。
  • 好答案。它还可以防止这种情况en.wikipedia.org/wiki/Most_vexing_parse
【解决方案2】:

这个例子的效果是一样的。

C c(3);direct intialization

检查T 的构造函数,并通过重载决议选择最佳匹配。然后调用构造函数来初始化对象。

C c{3};direct-list-initialization(C++11 起),

如果前一阶段没有产生匹配,T 的所有构造函数都参与重载决议,反对由括号初始化列表的元素组成的参数集,限制只有非缩小转换是允许的。

所以对于这两种情况,C::C(int) 都用于初始化对象。


根据C 的行为,C c(3);C c{3}; 之间的其他潜在差异包括:

【讨论】:

  • 谢谢。请问C c(3)C c{3}哪一种风格在OO的其他语言中更流行? Java 和 C# 两者都没有,这对吗?
  • @Ben 我不确定,我猜是C c(3)。列表初始化是从 C++11 引入的,在 C++ 中它被认为是现代风格。 :)
猜你喜欢
  • 1970-01-01
  • 2016-06-22
  • 2011-04-05
  • 1970-01-01
  • 2010-11-28
  • 2010-09-09
  • 2013-06-16
  • 2021-08-31
  • 2014-03-21
相关资源
最近更新 更多