参考资料:《C++ Primer习题集(第5版)》
目的:如何让一个类“行为像值”。
/*
* HasPtr.cpp
*
*
*/
#include <iostream>
#include <string>
using namespace std;
class HasPtr {
private:
string *ps;
int i;
public:
HasPtr(const string &s = string()): ps(new string(s)), i(0) {}//动态内存分配;
HasPtr(const HasPtr &p) : ps(new string(*p.ps)), i(p.i) {}//拷贝构造函数, *p.ps 表明是p.ps指针所指向的值;
HasPtr& operator = (const HasPtr &);//拷贝赋值运算符;//类内声明;
HasPtr& operator = (const string &);//赋予新string;
string& operator * ();//解引用;
~HasPtr();//析构函数;
};
//类外定义;
HasPtr:: ~HasPtr() {
delete ps;//释放string内存, 将调用string的析构函数;
}
inline//内联函数;
HasPtr& HasPtr:: operator = (const HasPtr &rhs) {
string *newps2 = new string(*rhs.ps);//拷贝指针指向的对象;
delete ps;//销毁原string;
ps = newps2;//指向新string;
i = rhs.i;//使用内置的int赋值;
return *this;//返回一个此对象的引用;
}
HasPtr& HasPtr:: operator = (const string &rhs) {
*ps = rhs;//ps指向的值赋值为rhs;
return *this;//返回一个此对象的引用;
}
string& HasPtr:: operator * () {
return *ps;//返回ps的解引用;
}
int main(int argc, char **argv) {
ios::sync_with_stdio(false);
cin.tie(NULL);
HasPtr h("hi mom!");
HasPtr h2(h);//行为类值, h2, h3, h指向不同的string;
HasPtr h3 = h;//调用拷贝构造函数;
h2 = "hi dad!";
h3 = "hi son!";
cout << "h: " << *h << endl;
cout << "h2: " << *h2 << endl;
cout << "h3: " << *h3 << endl;
return 0;
}
//如果未定义析构函数, 在销毁HasPtr对象时合成的析构函数不会释放指针ps, 造成内存泄漏;
//如果未定义拷贝构造函数, 在拷贝HasPtr对象时, 合成的拷贝构造函数会简单复制ps成员, 使得两个HasPtr指向相同的string;
//当其中一个HasPtr修改string内容时, 另一个HasPtr也被改变;
//如果同时定义了析构函数, 当销毁其中一个HasPtr时, ps指向的string被销毁, 另一个HasPtr的ps成为空指针;
/*
h: hi mom!
h2: hi dad!
h3: hi son!
*/