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

C++默认拷贝构造函数行为不符预期的原因咨询

你的C++浅拷贝问题解惑

嘿,你推理里的误区其实出在对p2.name = "Bill";这个操作的理解上,咱们一步步拆解来搞懂为什么实际输出和你预期不一样:

1. 默认拷贝构造函数的行为(浅拷贝)

你说的没错,C++的默认拷贝构造函数确实是浅拷贝:创建p2时,会把p1的每个成员变量的值直接拷贝给p2。所以一开始p1.name和p2.name指向的是同一块堆内存——就是p1构造时用new char[]分配的、存储着"Tom"的那块内存。

2. 为什么修改p2.name没影响p1.name?

关键就看这行代码:

p2.name = "Bill";

你以为这是在修改p2.name指向的内存内容,但实际上,这行代码做的是重新赋值指针本身:

  • "Bill"是一个字符串常量,它存储在程序的静态存储区,有自己独立的内存地址。
  • 这行代码把p2.name这个指针变量的值,从原来指向堆内存的地址,改成了指向"Bill"这个常量的地址。

而p1.name的指针值并没有被改变,它仍然指向原来那块存储着"Tom"的堆内存,所以当你输出p1.name时,自然会打印"Tom"。

3. 如何实现你预期的效果?

如果你想让修改p2的name同时影响p1,你需要修改指针指向的内存内容,而不是修改指针本身。比如用strcpy函数:

strcpy(p2.name, "Bill");

这样就会把"Bill"复制到p2.name(也就是p1.name)指向的堆内存里,此时输出p1.name就会得到"Bill"。不过要注意:原来的堆内存只分配了strlen("Tom")+1=4字节的空间,"Bill"刚好也是4字节(包含末尾的'\0'),不会越界;如果改成更长的字符串,就会导致内存越界,触发未定义行为。

额外提醒:浅拷贝的隐藏隐患

你的代码还有一个容易忽略的问题:当p1和p2生命周期结束时,它们的析构函数都会调用delete[] name,也就是对同一块堆内存释放两次,这属于双重释放,会触发未定义行为(比如程序崩溃、异常等)。解决这个问题的方法是自己实现深拷贝构造函数,在拷贝时为name重新分配内存并复制内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:38:59