☰
  • 首页
  • 规则分类
  • 项目介绍
search
•••

用列表初始化代替用等号或小括号的方式进行初始化

6.6.1 ID_missingBracedSyntax
目录 › next › previous

等号或小括号初始化不检查类型转换是否安全,列表初始化会进行相关检查,可避免数据丢失等问题,提高了安全性,而且列表初始化在语法形式上更统一,有助于提高可读性。

示例:

void foo(double x) {
    float a = x;   // Non-compliant, may loss data
    float b(x);    // Non-compliant, may loss data
    float c{x};    // Compliant, list-initialization, compile-time protected
    float d{static_cast<float>(x)};   // Compliant, intentional conversion
    ....
}

例中 a 和 b 的初始化可能存在数据丢失等问题,c 的初始化无法通过编译,使问题得以及时修正,d 为有意转换,可以通过编译。

在大多数情况下,列表出初始化均可代替等号或小括号初始化,如初始赋值、调用构造函数等:

struct A {
    int x{1};       // ‘x’ is set to 1
    A() = default;  // Default constructor
    A(int i): x{i}  // Overloaded constructor
    {}
};
A a{};        // Calls the default constructor
A b{1};       // Calls the overloaded constructor
A c{a};       // Copy-initialization
A d[]{1, 2};  // Initializate an array

struct B {
    int i, j;
};
B e{};        // Zero-initialization, members are set to 0
B f{1, 2};    // Members are set to 1 and 2 respectively

相比于列表初始化,小括号初始化的语法不统一:

B g();        // This is a function, not an object
B h = B();    // Zero-initialization, verbose

注意,例中 B g(); 是函数声明,易与对象定义混淆,改用 B g{}; 可以简练有效的对成员进行零初始化。

列表初始化的大括号及之间的内容称为“初始化列表”,初始化列表之前可以有一个等号,但 = {....} 是拷贝初始化,不带等号才是直接初始化,虽然复制成本可被优化,但仍应避免使用多余的符号。

struct C {
    int x;
    explicit C(int i): x{i} {}
};
C a{1};      // OK
C b = {1};   // Compile error

构造函数被 explicit 关键字限定,故无法进行拷贝初始化。

例外:

std::vector<int> v(5, 0);  // 5 elements with value 0
std::vector<int> w{5, 0};  // 2 elements, first is 5, second is 0

初始化列表的类型为 std::initializer_list,如果相关构造函数对其有重载,则调用重载了的构造函数。std::vector 对 initializer_list 进行了重载,可以像初始化数组一样初始化 vector,例中 v 有 5 个元素,每个元素都是 0,而 w 有两个元素,第一个是 5,第二个是 0,这一点列表初始化无法代替用括号的方式进行初始化。

相关

ID_narrowCast

依据

ISO/IEC 14882:2011 8.5.4

参考

C++ Core Guidelines ES.23
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.