为何C++默认拷贝构造未呈现浅拷贝效果?代码疑问解析
测试代码
#include<bits/stdc++.h> using namespace std; class student{ public: int age; string name; student(){ age = 0; name = ""; } void setName(string name){ this->name = name; } void setAge(int age){ this->age = age; } void print(){ cout<<"Name is: "<<this->name<<" "; cout<<"Age is: "<<this->age<<endl; } }; int main(){ student s1; s1.setAge(20); s1.setName("Ajay"); student s2(s1); s1.print(); cout<<endl; s2.print(); cout<<endl; s1.name[0]='B'; s1.print(); cout<<endl; s2.print(); cout<<endl; }
运行输出
Name is: Ajay Age is: 20
Name is: Ajay Age is: 20
Name is: Bjay Age is: 20
Name is: Ajay Age is: 20
疑问
按照浅拷贝的概念,修改s1的name首字符后,s2的name也应变为"Bjay",因为二者应共享内存,但实际修改未在s2中体现。请问该现象的原因是什么?两个对象是否共享内存?
解答
核心原因:std::string的拷贝是安全的独立内存拷贝
你的student类里的name是std::string类型,而非原始指针。C++默认拷贝构造函数会对每个成员执行成员级拷贝:对于int age这类基础类型直接复制值;对于std::string这类类类型成员,会调用它自身的拷贝构造函数。而std::string的拷贝构造函数会为新对象分配独立的内存存储字符串内容,不会和原对象共享同一块内存。浅拷贝的触发场景
浅拷贝导致的共享内存问题,只出现在类持有原始指针(比如char* name)的情况。此时默认拷贝构造函数只会复制指针的值,让两个对象的指针指向同一块内存,修改其中一个会影响另一个。但std::string已经封装了完整的内存管理逻辑,完全规避了这种风险。写时拷贝的补充说明
部分旧版C++标准库中,std::string采用写时拷贝策略:拷贝时先共享内存,直到其中一个对象修改内容时,才会真正分配新内存并复制数据。但即使是这种情况,当你执行s1.name[0]='B'时,会触发写时拷贝,为s1.name分配独立内存,所以修改后s2.name依然不受影响。
结论
两个student对象的name成员不共享内存,它们各自拥有独立的字符串存储空间,因此修改s1的name不会影响s2。
内容的提问来源于stack exchange,提问作者Radioactive

