类C,构造函数和统一初始化之间有什么区别?

TTBOMK,在C ++中有三种方法来初始化一个variables。

int x = 0; // C-like initialization int x (0); // Constructor initialization int x {0}; // Uniform initialization 

C ++ 11为统一初始化提供了一个更统一的语法来初始化不同types的variables,这些variables在C ++ 03中需要不同的语法。

类C,构造函数和统一初始化之间有什么区别? 我应该总是使用统一的初始化?

首先,我build议看一下Herb Sutter的以下谈话 ,他在这个话题中提出了一些build议。 大括号初始化讨论从23:00左右开始。

当你在谈论原始数据types时,所有3都会得到相同的结果。 我个人更喜欢坚持旧的int x = 0语法,但归结为个人偏好。

对于类types,括号初始化和老派构造函数初始化不是完全可以互换的。 例如:

 vector<int> v (100); // Creates a 100-element vector vector<int> v {100}; // Creates a 1-element vector, holding the value 100. 

这是因为std::vector有一个构造函数,它明确定义了std::initializer_list作为唯一的参数。 请记住这一点

 auto var = {1, 2}; 

创build一个std::initializer_listvar作为其标识符。

关于初始化列表的事情是,它们提供的一致性是事先可用的一个可喜的变化。 例如,如果你要用C ++初始化一个数组,你可以使用:

 int arr[] = {1, 2, 3, 4}; 

但是,如果你想用同样的元素初始化一个vector<int> ,你必须:

  1. 初始化上面的arr,然后通过arrarr + 4
  2. 分别创buildvector和push_back()元素或循环。

用C ++ 11,你可以使用

 vector<int> v = {1, 2, 3, 4}; // Same syntax. Nice! Note that the = is optional 

大括号初始化有用的另一个实例是它提供了一个解决方法,以C ++的最令人头痛的parsing 。 从谈话中,假设我们有两个类, originextents ,其实例可以被传递来构造rectangletypes的另一个对象。 以下声明:

 rectangle w(origin(), extents()); 

不允许使用originextents临时对象创buildrectangle对象,因为该语句被parsing为函数声明。 Tsk tsk。 所以通常情况下,你必须这样做:

 origin o; extents e; rectangle w(o, e); 

使用大括号初始化,您可以即时创build它们

 rectangle w {origin(), extents()}; 

将按预期工作,即传递给构造函数,该构造函数的第一个参数是一个origin对象,第二个是extents对象。

规则是针对对象,除非你有理由不使用大括号初始化。

c类,构造函数和统一初始化之间有什么区别?

对于像int这样的原始types,没有实际的区别。 所以我们来考虑一个类typesT

第一种风格相当于

 T x(T(0)); 

从初始化expression式创build临时对象,然后通过移动或复制x来初始化x 。 在实践中,移动或复制将被消除,从而结果与第二种方式相同; 唯一的区别是,如果没有可访问的副本或移动构造函数,则第一个将失败。

第二个直接使用一个构造函数初始化对象,该构造函数接受一个参数,如果没有合适的构造函数,则返回错误。

第三个取决于什么构造函数可用。

  • 如果有构造函数采取std::initializer_list ,它使用它;
  • 否则,如果有一个构造函数接受一个合适types的单个参数,则使用该参数;
  • 否则,如果它是一个成员的聚集(没有构造函数),则该成员初始化为零;
  • 否则,这是一个错误。

我应该总是使用统一的初始化?

不,有时你需要函数式初始化来区分initializer_list构造函数和其他参数types。 例如:

 std::vector<int> v1(10, 42); // 10 elements with value 42 std::vector<int> v2{10, 42}; // 2 elements with values 10 and 42 

你也不应该称之为“统一初始化”,因为它在任何有意义的意义上都不是“统一的”。 官方名称是“大括号初始化”。