MST

星途 面试题库

面试题:C++ 中赋值运算符与拷贝构造函数性能比较之基础分析

在 C++ 中,假设有一个简单类 `MyClass`,包含一个动态分配的数组成员。请分别实现该类的拷贝构造函数和赋值运算符重载,并简要说明在什么场景下拷贝构造函数和赋值运算符的性能表现会有所不同。
31.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <cstring>

class MyClass {
private:
    int* data;
    int size;

public:
    // 构造函数
    MyClass(int s) : size(s) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = 0;
        }
    }

    // 拷贝构造函数
    MyClass(const MyClass& other) : size(other.size) {
        data = new int[size];
        std::memcpy(data, other.data, size * sizeof(int));
    }

    // 赋值运算符重载
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            delete[] data;
            size = other.size;
            data = new int[size];
            std::memcpy(data, other.data, size * sizeof(int));
        }
        return *this;
    }

    // 析构函数
    ~MyClass() {
        delete[] data;
    }
};

性能表现不同的场景:

  1. 拷贝构造函数
    • 场景:当通过值传递对象或者初始化一个新对象时会调用拷贝构造函数。例如:
    MyClass obj1(5);
    MyClass obj2 = obj1; // 调用拷贝构造函数
    void func(MyClass obj);
    func(obj1); // 在函数调用时,形参通过值传递,调用拷贝构造函数
    
    • 性能特点:因为是创建新对象,通常会涉及全新的内存分配和数据复制,开销较大。如果对象较大,这种开销会更明显。
  2. 赋值运算符重载
    • 场景:当已经存在的对象被赋值为另一个对象时调用赋值运算符重载。例如:
    MyClass obj1(5);
    MyClass obj2(3);
    obj2 = obj1; // 调用赋值运算符重载
    
    • 性能特点:在赋值运算符重载中,首先要检查是否是自赋值(this != &other),如果不是自赋值,要释放原有内存,然后重新分配内存并复制数据。相比于拷贝构造函数,它不需要创建全新对象,在已经有对象且只是需要更新其内容的场景下,可能会比拷贝构造函数高效,尤其是在对象已经较大且需要频繁赋值的情况下。如果对象没有动态分配的资源,简单的成员变量赋值开销较小。但如果有动态资源,释放和重新分配内存的操作也会带来一定开销。