当前位置: 首页 > 知识库问答 >
问题:

列表初始化(使用大括号)的优点是什么?

微生宝
2023-03-14
MyClass a1 {a};     // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);

为什么?

共有3个答案

储修谨
2023-03-14

使用大括号初始化有很多原因,但您应该知道initializer_list

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

假设您没有遇到这样的类,没有什么理由不使用intiezer列表。

常英毅
2023-03-14

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

  • 如果我正在创建的对象在概念上包含我在构造函数中传递的值(例如容器、POD结构、原子、智能指针等),那么我正在使用大括号。
  • 如果构造函数类似于普通函数调用(它执行一些或多或少复杂的操作,这些操作由参数参数化),那么我使用的是普通函数调用语法。
  • 对于默认初始化,我总是使用花括号。
    首先,这样我总是确保对象被初始化,而不管它是例如一个“真实”类,它具有无论如何都会被调用的默认构造函数还是内置/POD类型。其次,在大多数情况下,它与第一条规则一致,因为默认初始化对象通常表示一个“空”对象。

根据我的经验,这个规则集可以比默认使用花括号更一致地应用,但是当它们不能使用或者与带括号的“正常”函数调用语法有不同的含义时,必须明确记住所有异常(调用不同的重载)。

例如,它非常适合标准库类型,如std::向量

vector<int> a{10, 20};   //Curly braces -> fills the vector with the arguments

vector<int> b(10, 20);   //Parentheses -> 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
姚才捷
2023-03-14

基本上是从Bjarne Stroustrup的“C编程语言第4版”中复制和粘贴的:

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

    < li >一个整数不能转换为另一个不能保存其值的整数。例如,允许char到int,但不允许int到char。 < li >浮点值不能转换为不能保存其值的另一种浮点类型。例如,允许float to double,但不允许double to float。 < li >浮点值不能转换为整数类型。 < li >整数值不能转换为浮点类型。

示例:

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)

}

只有在使用< code>auto关键字来获取由初始值设定项确定的类型时,才会优先使用=而不是{}。

示例:

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

除非有充分的理由,否则最好使用{}初始化。

 类似资料:
  • Java中的双大括号初始化语法()是什么?

  • 我已经在网上搜索了这个问题的答案,但我还没有找到一个满意的答案。我想知道初始化结构和类类型的对象的所有规则是什么,特别是在构造函数与带括号的初始化列表方面。结构与类的规则也不同吗? 让我们假设有一个名为矩形的类或结构。 我尝试用C语言中通常使用的方式初始化矩形r,使用一个普通的带括号的初始值设定项列表。但是,g给出以下错误: 嗯……嗯。。。。乍一看,这并不是很有用的错误消息。然而,我认为它与构造函

  • 问题内容: 我用下面的代码。两者在我的应用程序中都运行良好。 情况1。 情况2 但是我有一些问题: 在性能方面哪个更好? 在哪种情况下,请选择案例2? 问题答案: 情况2在性能上是更好的BUT:它返回一个大小不变的List。意味着您不能在其中添加/删除元素: 返回由指定数组支持的 固定大小的 列表。(将返回的列表更改为“直写”到数组。)

  • 我需要用大量的整数值预先填充列表。 除了迭代,还有更快的方法吗? 当前代码: 此代码位于一个非常频繁创建的类的构造函数中,因此我希望它尽可能高效(read:性能而不是代码行)

  • 问题内容: 在Java的“ 隐藏功能”中,最常见的答案是,其语法非常诱人: 此成语创建一个匿名内部类,其中仅包含一个实例初始化程序,该实例“可以使用包含范围内的任何方法”。 主要问题:这听起来像效率低下吗?它的使用是否应仅限于一次性初始化?(当然还有炫耀!) 第二个问题:新的HashSet必须是实例初始化程序中使用的“ this”……任何人都可以阐明该机制吗? 第三个问题:这个习惯用法是否太晦涩,