Closed southmountain closed 8 years ago
为什么不直接对 *ps 赋值,而是要先delete ps,释放掉它的内存空间,再重新申请空间赋值?
首先, 完全可以直接赋值, 因为*ps
是std::string
类型.
然后, 为什么这里写的如此啰嗦?
直接原因是: 为了和书上的例子保持一致, 请见: 13.2.1 小节 Valuelike Copy-Assignment Operator 的例子.
根本原因是: 这个 HasPtr 的例子是这本书的一个瑕疵. 因为 ps
这个成员弄成 string*
非常莫名其妙. 完全可以直接用 std::string
, 从而避免用指针.(也就避免了内存的管理)
试想, 如果有一个成员是 int *
, 然后构造函数里会 new 一个 int
型的数组. 那么它的拷贝构造, 和拷贝赋值会怎么写?
std::string* new_ps = new std::string(*hp.ps);
delete ps;
ps = new_ps;
这三步, 诠释的是一种通用的解决方案. 即先 new 出一个新临时资源, 然后析构原始资源, 最后将原始指针指向新的临时资源.
对这三步进一步的优化, 应该是著名的 Copy-and-swap idiom.
对于该技巧的更多阐述请见: http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
回到原来的问题, 如果先忽略 std::string
的特殊性, 结合Valuelike Copy-Assignment Operator 的知识, 考虑为什么这样分三步写, 能更加安全和清晰.
最终会考虑为何要引入 swap 函数.
这就像一条隐隐的脉络, 让你更了解 C++ 的一些 trick 的深层原因.
本答案和书一样, 目的都是引导新手考虑语言的问题, 而并非是引导工程实践上的"优化".
多谢
参考答案 HasPtr& operator=(const HasPtr& hp) { std::string* new_ps = new std::string(hp.ps); delete ps; ps = new_ps; i = hp.i; return this; } 为什么不直接对 ps 赋值,而是要先delete ps,释放掉它的内存空间,再重新申请空间赋值? HasPtr&operator=(const HasPtr &hp){ ps = hp.ps; i = hp.i; return this; }