C++11新特性—列表初始化以及初始化列表概念的区别

在C++中,初始化列表和列表初始化是两个不同的概念,尽管它们都涉及到对象的初始化。

初始化列表(Initializer List)

初始化列表用于在构造函数中初始化类成员变量。它的语法是在构造函数的参数列表后面加一个冒号,然后列出成员变量的初始化方式。例如:

class MyClass {
public:
    MyClass(int a, int b) : x(a), y(b) {}
private:
    int x;
    int y;
};

使用初始化列表有几个优点:

1. 提高效率

初始化列表直接调用构造函数来初始化成员变量,而不是先调用默认构造函数,再在构造函数体内赋值。对于某些类类型的数据(如对象、容器),这种方式可以避免额外的赋值操作,提高性能。上面的例子中,ab 在构造函数中直接通过初始化列表被初始化,避免了默认初始化后的再赋值操作。

当你在构造函数体内进行成员变量赋值时,实际上分为两个步骤:

  1. 成员变量的默认构造:在进入构造函数体之前,C++会自动调用成员变量的默认构造函数来初始化这些成员变量。
  2. 在构造函数内赋值:进入构造函数体后,显式地进行赋值操作(比如调用赋值运算符),这会再次对这些成员变量进行赋值操作。

这意味着,对于一个非基础类型的成员变量,默认构造和赋值操作是分开的,因此会导致:

  • 先调用一次默认构造函数(在进入构造函数之前)。
  • 再调用赋值运算符进行赋值(在构造函数体内)。

2. 初始化常量成员

类中的 const 成员变量必须通过初始化列表初始化,因为常量成员变量一旦初始化后便不能被修改。

class MyClass {
public:
    MyClass(int val) : constantVal(val) {}
private:
    const int constantVal;
};

3. 初始化引用类型成员

引用类型成员变量必须通过初始化列表进行初始化,因为引用必须在其定义时就被绑定到某个对象上,无法通过赋值的方式修改。

class MyClass {
public:
    MyClass(int& ref) : myRef(ref) {}
private:
    int& myRef;
};

4. 初始化需要特定构造函数的成员

如果类成员对象没有默认构造函数(即没有无参构造函数),则必须使用初始化列表来调用带参数的构造函数。

class AnotherClass {
public:
    AnotherClass(int) {}  // 只有带参数的构造函数
};

class MyClass {
public:
    MyClass(int val) : obj(val) {}  // 必须使用初始化列表
private:
    AnotherClass obj;
};

总结:初始化列表必须使用的情况

  1. 常量成员 (const)
  2. 引用成员 (&)
  3. 没有默认构造函数的成员对象

此外,使用初始化列表也更符合 RAII 原则(资源获取即初始化),提高代码的效率和可读性。

列表初始化(List Initialization)

列表初始化是C++11引入的一种新的初始化方式,使用花括号{}来初始化变量。它可以用于初始化内置类型、STL容器以及自定义类型。例如:

int arr[] = {1, 2, 3}; // 数组初始化
std::vector<int> vec = {1, 2, 3}; // STL容器初始化
MyClass obj = {1, 2}; // 自定义类型初始化

列表初始化的优点包括:

  1. 统一的语法:可以用于多种类型的初始化
  2. 防止窄化转换:如果初始化过程中存在可能导致数据丢失的类型转换,编译器会报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值