MST

星途 面试题库

面试题:C++ 中拷贝构造函数和赋值运算符重载的区别

请详细阐述 C++ 中拷贝构造函数和赋值运算符重载在功能、调用场景以及实现上的区别,并举例说明。
26.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

功能区别

  1. 拷贝构造函数:用于创建一个新对象,该对象是另一个同类对象的副本。它主要用于初始化新对象。
  2. 赋值运算符重载:用于将一个已存在对象的值赋给另一个已存在对象。它主要用于改变已存在对象的状态。

调用场景区别

  1. 拷贝构造函数
    • 对象初始化:当使用一个已存在对象初始化新对象时,例如 ClassA a; ClassA b(a); 或者 ClassA b = a;(这种初始化形式会调用拷贝构造函数,而非赋值运算符)。
    • 函数参数传递:当对象以值传递方式作为函数参数时,会调用拷贝构造函数创建一个临时副本传入函数。
    • 函数返回值:当函数返回一个对象时,会调用拷贝构造函数创建一个临时对象作为返回值。
  2. 赋值运算符重载
    • 对象赋值:当对已存在的对象进行赋值操作时,例如 a = b;,这里 ab 都已经是初始化过的对象。

实现区别

  1. 拷贝构造函数
    • 其函数签名形式为 ClassName(const ClassName& other)
    • 在实现时,通常为新对象分配内存并将源对象的数据成员逐一复制到新对象中。对于包含动态分配内存的类,需要深拷贝,避免浅拷贝带来的内存管理问题。
  2. 赋值运算符重载
    • 其函数签名形式为 ClassName& operator=(const ClassName& other)
    • 在实现时,首先要检查是否是自赋值(if (this == &other) return *this;),然后释放当前对象的资源(如果有动态分配的资源),再为当前对象重新分配内存并复制源对象的数据成员。

举例说明

#include <iostream>
#include <cstring>

class MyString {
private:
    char* str;
    int length;
public:
    // 构造函数
    MyString(const char* s = nullptr) {
        if (s == nullptr) {
            length = 0;
            str = new char[1];
            str[0] = '\0';
        }
        else {
            length = strlen(s);
            str = new char[length + 1];
            strcpy(str, s);
        }
    }

    // 拷贝构造函数
    MyString(const MyString& other) {
        length = other.length;
        str = new char[length + 1];
        strcpy(str, other.str);
    }

    // 赋值运算符重载
    MyString& operator=(const MyString& other) {
        if (this == &other)
            return *this;
        delete[] str;
        length = other.length;
        str = new char[length + 1];
        strcpy(str, other.str);
        return *this;
    }

    // 析构函数
    ~MyString() {
        delete[] str;
    }

    void print() {
        std::cout << str << std::endl;
    }
};

int main() {
    MyString s1("Hello");
    MyString s2(s1); // 调用拷贝构造函数
    MyString s3;
    s3 = s1; // 调用赋值运算符重载

    s1.print();
    s2.print();
    s3.print();

    return 0;
}

在上述代码中,MyString 类展示了拷贝构造函数和赋值运算符重载的实现。s2(s1) 调用拷贝构造函数初始化 s2s3 = s1 调用赋值运算符重载为 s3 赋值。