You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

赋值运算符可替代拷贝构造函数拷贝对象值,为何仍需拷贝构造函数?

为啥C++里有了赋值运算符还需要拷贝构造函数?

这问题问得太到位了!刚学C++面向对象的朋友几乎都会有这个疑问,咱们结合你的代码和实际场景来掰扯清楚。

首先得明确:拷贝构造函数和赋值运算符的作用场景完全不一样,根本不是互相替代的关系。

核心区别:初始化新对象 vs 更新已有对象

  • 拷贝构造函数是用来创建一个全新的对象,并且直接用另一个已存在的对象的内容来初始化它。比如你代码里的example b(a);(哦对,你代码里笔误写成example a(b);啦,应该是创建新对象b),这时候b还不存在,是刚被定义出来的,必须通过拷贝构造来完成初始化。
  • 赋值运算符b = a;则是给已经存在的对象赋值,这时候b已经被创建(不管是默认构造还是其他方式初始化过),只是把a的值覆盖给它。

你试试把代码改成这样,就能直观看到区别:

#include <iostream>
using namespace std;

class example {
    int data;
public:
    example() { cout << "默认构造函数被调用" << endl; }
    example(int x) { data = x; cout << "带参构造函数被调用" << endl; }
    example(const example& other) { data = other.data; cout << "拷贝构造函数被调用" << endl; }
    example& operator=(const example& other) { data = other.data; cout << "赋值运算符被调用" << endl; return *this; }
};

int main() {
    example a(50); // 调用带参构造
    example b(a);  // 调用拷贝构造:创建新对象b并初始化
    example c;     // 调用默认构造:先创建c
    c = a;         // 调用赋值运算符:给已存在的c赋值
    return 0;
}

运行这段代码,你会清晰看到两个函数被调用的时机完全不同。

这些场景必须用拷贝构造函数

如果没有拷贝构造函数,很多C++的基础操作都会直接失效:

  • 函数传值参数:比如定义void print_example(example obj),当你调用print_example(a)时,会创建一个obj的拷贝,这一步必须调用拷贝构造函数。
  • 函数返回对象:比如example create_example(int x) { return example(x); },返回的临时对象也是通过拷贝构造来初始化的(虽然现代编译器可能做RVO优化,但标准层面依然要求拷贝构造函数是可访问的)。
  • 容器存储对象:比如vector<example> vec; vec.push_back(a);,push_back的时候会把a拷贝到容器里,这也需要拷贝构造。

浅拷贝的坑:自定义拷贝构造的必要性

另外,当你的类里包含动态分配的资源(比如指针、堆内存)时,编译器默认生成的拷贝构造函数只会做浅拷贝——也就是直接复制成员变量的值。比如:

class String {
    char* str;
public:
    String(const char* s) {
        str = new char[strlen(s)+1];
        strcpy(str, s);
    }
    ~String() { delete[] str; }
};

如果用默认拷贝构造创建新对象String s2(s1);,s1和s2的str指针会指向同一块堆内存,当两个对象析构时,会重复释放同一块内存,直接导致程序崩溃。这时候必须自定义拷贝构造函数来做深拷贝,重新分配内存并复制内容,而赋值运算符也需要做同样的处理,但两者的场景还是完全分开的。

总结一下:拷贝构造和赋值运算符是各司其职的,一个管“生新对象”,一个管“给老对象换内容”,缺了哪个都不行~

内容的提问来源于stack exchange,提问作者Ibra noor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:24:23