MST

星途 面试题库

面试题:C++初始化成员列表与构造函数体赋值的差异

详细阐述在C++中,使用初始化成员列表和在构造函数体中对成员变量进行赋值这两种方式有哪些不同,从性能、适用场景等方面举例说明。
18.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

性能方面

  1. 初始化成员列表
    • 对于类类型成员变量,初始化成员列表是直接调用成员变量的构造函数进行初始化。例如,假设有一个类 MyClass 包含一个 std::string 成员变量 str
    class MyClass {
    private:
        std::string str;
    public:
        MyClass(const std::string& s) : str(s) {}
    };
    
    • 这种方式效率较高,因为它避免了先默认构造成员变量,然后再在构造函数体中赋值的额外开销。在上述例子中,str 直接使用传入的 s 进行初始化,而不是先默认构造 str,再调用 str 的赋值运算符。
  2. 构造函数体中赋值
    • 对于类类型成员变量,会先调用成员变量的默认构造函数,然后在构造函数体中再调用赋值运算符进行赋值。例如:
    class MyClass {
    private:
        std::string str;
    public:
        MyClass(const std::string& s) {
            str = s;
        }
    };
    
    • 这种方式会产生额外的开销,因为先默认构造了 str,然后又进行了一次赋值操作,性能相对初始化成员列表较差。

适用场景方面

  1. 初始化成员列表
    • 常量成员变量:常量成员变量必须在定义时初始化,所以只能使用初始化成员列表。例如:
    class MyClass {
    private:
        const int num;
    public:
        MyClass(int n) : num(n) {}
    };
    
    • 引用成员变量:引用成员变量也必须在定义时初始化,同样只能使用初始化成员列表。例如:
    class MyClass {
    private:
        int& ref;
    public:
        MyClass(int& n) : ref(n) {}
    };
    
    • 没有默认构造函数的类类型成员变量:如果类的成员变量没有默认构造函数,就无法在构造函数体中先默认构造再赋值,必须使用初始化成员列表。例如:
    class NoDefaultConstructor {
    public:
        NoDefaultConstructor(int n);
    };
    class MyClass {
    private:
        NoDefaultConstructor obj;
    public:
        MyClass(int n) : obj(n) {}
    };
    
  2. 构造函数体中赋值
    • 当成员变量的初始化逻辑非常复杂,需要在构造函数体中进行一些计算或者条件判断后再赋值时,构造函数体中赋值可能更合适。例如:
    class MyClass {
    private:
        int num;
    public:
        MyClass(int a, int b) {
            if (a > b) {
                num = a;
            } else {
                num = b;
            }
        }
    };
    
    • 在这种情况下,使用初始化成员列表会使代码变得复杂,而在构造函数体中进行赋值则更直观和易读。