为了账号安全,请及时绑定邮箱和手机立即绑定

为什么列表初始化(使用大括号)比其他方法更好?

为什么列表初始化(使用大括号)比其他方法更好?

C++
慕勒3428872 2019-06-28 15:35:55
为什么列表初始化(使用大括号)比其他方法更好?MyClass a1 {a};     // clearer and less error-prone than the other threeMyClass a2 = {a};MyClass a3 = a;MyClass a4(a);为什么?我找不到答案,所以让我回答我自己的问题。
查看完整描述

3 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

基本上是从Bjarne Stroustrup那里复制和粘贴的C+编程语言第4版:

列表初始化不允许缩小范围(§iso.8.5.4)。即:

  • 一个整数不能转换为另一个不能保存其值的整数。例如,char to int是允许的,而不是int to char。
  • 浮点值不能转换为另一种不能保存其值的浮点类型.例如,允许浮动到双倍,但不允许双倍浮动。
  • 浮点值不能转换为整数类型.
  • 整数值不能转换为浮点类型.

例子:

void fun(double val, int val2) {

    int x2 = val; // if val==7.9, x2 becomes 7 (bad)

    char c2 = val2; // if val2==1025, c2 becomes 1 (bad)

    int x3 {val}; // error: possible truncation (good)

    char c3 {val2}; // error: possible narrowing (good)

    char c4 {24}; // OK: 24 can be represented exactly as a char (good)

    char c5 {264}; // error (assuming 8-bit chars): 264 cannot be 
                   // represented as a char (good)

    int x4 {2.0}; // error: no double to int value conversion (good)}

这个使用时,=优于{}的情况auto关键字,以获取由初始化器确定的类型。

例子:

auto z1 {99}; // z1 is an initializer_list<int>auto z2 = 99; // z2 is an int

结语

喜欢{}初始化而不是其他选项,除非您有很强的理由不这样做。


查看完整回答
反对 回复 2019-06-28
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

使用大括号初始化有很多原因,但是您应该知道这个initializer_list<>构造函数优于其他构造函数。,异常是默认构造函数。这将导致构造函数和模板出现问题,其中类型T构造函数可以是初始化程序列表,也可以是普通的旧ctor。

struct Foo {
    Foo() {}

    Foo(std::initializer_list<Foo>) {
        std::cout << "initializer list" << std::endl;
    }

    Foo(const Foo&) {
        std::cout << "copy ctor" << std::endl;
    }};int main() {
    Foo a;
    Foo b(a); // copy ctor
    Foo c{a}; // copy ctor (init. list element) + initializer list!!!}

假设您没有遇到这样的类,那么就没有什么理由不使用减缩器列表了。


查看完整回答
反对 回复 2019-06-28
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

关于使用列表初始化的优点,已经有了很好的答案,但是我个人的经验法则不是尽可能使用大括号,而是让它依赖于概念意义:

  • 如果我正在创建的对象在概念上持有我在构造函数中传递的值(例如容器、POD结构、Atomics、智能指针等),那么我将使用大括号。
  • 如果构造函数类似于普通函数调用(它执行一些或多或少由参数化的复杂操作),那么我将使用普通函数调用语法。
  • 对于默认初始化,我总是使用大括号。


    首先,我总是确信对象是初始化的,而不管它是一个“真实的”类,它有一个默认的构造函数,它无论如何都会被调用,或者是内置/POD类型。其次,在大多数情况下,它与第一条规则一致,因为默认的初始化对象通常表示“空”对象。

在我的经验中,与默认情况下使用大括号相比,可以更一致地应用此规则集,但当所有异常不能被使用或具有与带括号的“正常”函数调用语法不同的含义时,必须显式地记住它们(调用不同的重载)。

例如,它与标准库类型(如std::vector:

vector<int> a{10,20};   //Curly braces -> fills the vector with the argumentsvector<int> b(10,20);   //Parenthesis -> uses arguments to parametrize some functionality,                          vector<int> c(it1,it2); //like filling the vector with 10 integers or copying a range.vector<int> d{};      //empty braces -> default constructs vector, which is equivalent
                      //to a vector that is filled with zero elements


查看完整回答
反对 回复 2019-06-28
  • 3 回答
  • 0 关注
  • 759 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信