// Person通过指针拥有string class Person { public: Person(string name) { pName_ = new string(name); } ~Person() { delete pName_; } void printName() { cout << *pName_; } private: string* pName_; }; int main() { vector<Person> persons; persons.push_back(Person("George")); persons.front().printName(); //这里会崩 cout << "Goodbye" << endl; } //persons.push_back(Person("George")); 事实上该行代码可以分解成以下步骤 // 1. "George" 被构造 // 2. "George"的一个副本保存到(浅拷贝) // 3. "George"被销毁 // Solution 1: 定义拷贝构造和拷贝赋值实现深拷贝 Person(const Person& rhs) { pName_ = new string(*(rhs.pName())); } Person& operator=(const Person& rhs); string* pName() const { return pName_; } // Solution 2: 禁用拷贝构造和拷贝赋值 // 对C++ 11,使用=delete // for C++ 03, 声明但不定义 Person(const Person& rhs); Person& operator=(const Person& rhs); // 如果禁用之后仍然需要拷贝,使用clone() // 显式的拷贝 Person* clone() { return (new Person(*(pName_))); } // 更推荐方法2: // 1. 因为拷贝构造和拷贝赋值经常并不需要 // 2. 使拷贝显式,隐式拷贝容易出现bug // 3. clone可以利用多态实现虚构造函数,自动根据指针所指对象的类型拷贝基类或者派生类对象 class Dog { public: virtual Dog* clone() { return (new Dog(*this)); } //co-variant return type 允许覆写函数具有不同的返回类型,只要返回类型由基类的返回类型派生得到 }; class Yellowdog : public Dog { virtual Yellowdog* clone() { return (new Yellowdog(*this)); } }; void foo(Dog* d) { // d 是Yellowdog //Dog* c = new Dog(*d); // c 是Dog,不是我们想要的 Dog* c = d->clone(); // c是Yellowdog //... // } int main() { Yellowdog d; foo(&d); } // C++ 11 的方法: // shared_ptr<string> pName_; // 大多数情况下用unique_ptr也可以, 但是跟STL container一起使用时必须使用shared_ptr, // 因为STL容易要求元素时可拷贝的
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!
· langchain0.3教程:从0到1打造一个智能聊天机器人