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

标签 c++ c++11 initialization c++03 variable-initialization

据我所知,有三种方法可以在C++中初始化变量。

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

C++11启用了统一初始化,以提供更统一的语法来初始化不同类型的变量,这需要在C++03中使用不同的语法。

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

最佳答案

首先,我建议您看一下Herb Sutter的following talk,他在其中提供了有关该主题的一些建议。大括号初始化讨论始于around 23:00

当您谈论原始数据类型时,所有这三种都会产生相同的结果。我个人更喜欢使用旧的int x = 0语法,但这归结为个人喜好。

对于类类型,括号初始化和老式构造函数初始化不能完全互换。例如:

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};

创建一个std::initializer_list,并将var作为其标识符。

关于初始化程序列表的事情是,它们提供了一致性,这是对先前可用列表的可喜变化。例如,如果要使用C++初始化数组,则可以使用:
int arr[] = {1, 2, 3, 4};

但是,如果要使用相同的元素初始化vector<int>,则必须:
  • 首先初始化上面的arr,然后传递arrarr + 4
  • 单独或循环创建 vector 和push_back()元素。

  • 使用C++ 11,您可以使用
    vector<int> v = {1, 2, 3, 4}; // Same syntax. Nice! Note that the = is optional
    

    大括号初始化很有用的另一个实例是,它为C++的most vexing parse提供了一种解决方法。在讨论中,假设我们有两个类originextents,可以将其实例传递来构造另一个类型为rectangle的对象。以下语句:
    rectangle w(origin(), extents());
    

    不允许您使用rectangleorigin临时对象创建extents对象,因为该语句被解析为函数声明。 sk因此,通常,您必须执行以下操作:
    origin  o;
    extents e;
    rectangle w(o, e);
    

    通过括号初始化,您可以即时创建它们,并且
    rectangle w {origin(), extents()};
    

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

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

    关于c++ - 类C,构造函数和统一初始化之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61008507/

    相关文章:

    C# 字符串编码和 LocalAlloc

    c++ - 如何在cryptoki中重命名容器名称

    c++ - 在可变参数模板中使用声明

    c++ - 使用初始化列表中的引用初始化对象成员

    c++ - 有限状态机解析器

    C++11 : Are there reasons why some Regular Types should not have `std::hash` specialised?

    c++ - 根据另一个 vector 对点 vector 进行排序

    c++ - 二维 std::array 上的初始化列表

    arrays - 在 Julia 中,如何初始化一个二维数组(矩阵),其中每个元素都是一个列向量?

    java - 我应该保持 Java 中的实例变量始终初始化吗?