MST

星途 面试题库

面试题:C++初始化成员列表与性能优化

考虑一个复杂的C++类ComplexClass,它包含多个成员变量,其中一些是自定义类类型,一些是基本数据类型。请详细阐述在构造函数中使用初始化成员列表相比于在构造函数体内赋值,对性能有哪些影响?在什么情况下性能差异最为显著?并通过代码示例说明如何利用初始化成员列表进行性能优化。
32.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

性能影响

  1. 对于自定义类类型成员
    • 初始化成员列表:直接调用自定义类的构造函数进行初始化,一步到位。例如,假设有一个自定义类MyClass,在ComplexClass的构造函数初始化列表中初始化MyClass成员,会直接使用MyClass的构造函数进行初始化。
    • 构造函数体内赋值:首先会调用自定义类的默认构造函数创建对象,然后再调用赋值运算符进行赋值,这涉及两次操作,性能相对较差。
  2. 对于基本数据类型成员
    • 初始化成员列表:直接初始化,效率较高。
    • 构造函数体内赋值:虽然也能完成赋值操作,但在一些编译器优化不足的情况下,可能会有轻微的性能差异,初始化列表的方式逻辑上更直接。

性能差异显著的情况

ComplexClass包含多个自定义类类型成员时,性能差异最为显著。因为每个自定义类类型成员在构造函数体内赋值都会经历默认构造和赋值两次操作,而使用初始化成员列表则只进行一次构造操作。随着自定义类类型成员数量的增加,这种性能差距会更加明显。

代码示例

#include <iostream>
class MyClass {
public:
    MyClass(int value) : data(value) {
        std::cout << "MyClass constructor with value: " << data << std::endl;
    }
    MyClass() : data(0) {
        std::cout << "MyClass default constructor" << std::endl;
    }
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            data = other.data;
            std::cout << "MyClass assignment operator" << std::endl;
        }
        return *this;
    }
    ~MyClass() {
        std::cout << "MyClass destructor" << std::endl;
    }
private:
    int data;
};

class ComplexClass {
public:
    // 使用初始化成员列表
    ComplexClass(int num, MyClass obj) : basicData(num), customObj(obj) {
        std::cout << "ComplexClass constructor with init list" << std::endl;
    }
    // 构造函数体内赋值
    ComplexClass(int num, MyClass obj) {
        basicData = num;
        customObj = obj;
        std::cout << "ComplexClass constructor with in - body assignment" << std::endl;
    }
private:
    int basicData;
    MyClass customObj;
};

int main() {
    MyClass myObj(10);
    // 使用初始化成员列表构造ComplexClass对象
    ComplexClass obj1(20, myObj);
    // 使用构造函数体内赋值构造ComplexClass对象
    ComplexClass obj2(30, myObj);
    return 0;
}

在上述代码中,ComplexClass类有一个基本数据类型成员basicData和一个自定义类类型成员customObj。通过对比两种构造方式,可以明显看到使用初始化成员列表在初始化customObj时更高效,避免了先默认构造再赋值的额外操作。