MST

星途 面试题库

面试题:C++中对象成员初始化列表与在构造函数体内初始化的区别

在C++中,说明使用对象成员初始化列表和在构造函数体内对成员变量进行初始化,这两种方式有何区别?并举例说明在哪些场景下使用初始化列表更具优势。
34.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

区别

  1. 初始化顺序
    • 初始化列表:按照成员变量在类中声明的顺序进行初始化,而不是按照初始化列表中出现的顺序。
    • 构造函数体:先调用成员变量的默认构造函数进行初始化(如果没有在初始化列表中初始化),然后在构造函数体内对成员变量进行赋值操作。
  2. 性能
    • 初始化列表:对于一些对象成员,直接初始化可能效率更高,因为避免了先默认构造再赋值的过程。例如对于const成员变量和引用成员变量,必须使用初始化列表初始化,因为它们不能被赋值。
    • 构造函数体:由于存在先默认构造再赋值的过程,对于一些复杂对象,可能会有额外的性能开销。
  3. 适用场景
    • 初始化列表:适用于const成员变量、引用成员变量的初始化,以及对象成员初始化希望直接构造而非先默认构造再赋值的场景。
    • 构造函数体:适用于简单的基本数据类型成员变量的赋值操作,在不需要考虑性能优化或者初始化逻辑比较复杂,需要在构造函数体中进行一些条件判断等操作时使用。

示例说明初始化列表优势场景

#include <iostream>
#include <string>

class Data {
public:
    Data(int value) : num(value) {
        std::cout << "Data constructor with value: " << num << std::endl;
    }
    ~Data() {
        std::cout << "Data destructor" << std::endl;
    }
private:
    int num;
};

class MyClass {
public:
    // 使用初始化列表初始化const成员变量和对象成员
    MyClass(int val, const std::string& str) : constVar(val), data(val), strObj(str) {
        std::cout << "MyClass constructor" << std::endl;
    }
    // 错误示例,如果在构造函数体中初始化constVar会报错
    // MyClass(int val, const std::string& str) {
    //     constVar = val; // 错误,const变量不能被赋值
    //     data = Data(val); // 先默认构造data,再赋值,效率低
    //     strObj = str;
    // }
private:
    const int constVar;
    Data data;
    std::string strObj;
};

int main() {
    MyClass obj(10, "Hello");
    return 0;
}

在上述示例中,MyClass类中有const成员变量constVar,必须在初始化列表中初始化。Data类型的对象成员data如果在构造函数体中赋值,会先默认构造data,然后再赋值,使用初始化列表可以直接构造data,提高效率。所以在这些场景下,使用初始化列表更具优势。