第十三章拷贝控制实例

Best Practices:拷贝赋值运算符通常执行拷贝构造函数和析构函数中也要做的工作。这种情况下,公共的工作应该放在private的工具函数中完成。

#include<iostream>
#include<string>
#include<set>
using namespace std;
class Message;
class Folder {
public:
	void addMsg(Message* msg) {
		Msg.insert(msg);
	}
	void remMsg(Message* msg) {
		Msg.erase(msg);
	}
private:
	set<Message*> Msg;
};

class Message {
	friend class Folder;
public:
	//显示构造函数,有一个默认参数,也是默认构造函数
	//因为调用set,所以folders被隐式初始化为空集
	explicit Message(const string& str = "") :contents(str) {};
	//拷贝构造函数
	Message(const Message&);
	//拷贝赋值函数
	Message& operator=(const Message&);
	~Message();

	//将Message存放到指定Folder之中
	void save(Folder&);
	void remove(Folder&);
private:
	string contents;
	set<Folder*> folders;

	void add_to_folders(const Message&);
	void remove_from_folders();
	void swap(Message& lhs, Message& rhs);
};
//从Msg添加指针到folders中
void Message::save(Folder& f) {
	folders.insert(&f);
	f.addMsg(this);
}
void Message::remove(Folder& f) {
	folders.erase(&f);
	f.remMsg(this);
}

//拷贝的时候是两个msg,要把其中一个msg的每一个folders都添加另一个msg,即this
void Message::add_to_folders(const  Message& msg) {
	for (auto f : msg.folders)
		f->addMsg(this);
}
//删除folder中本Message
void Message::remove_from_folders() {
	for (auto f : folders)
		f->remMsg(this);
}
//拷贝构造函数
Message::Message(const Message& msg) :contents(msg.contents),folders(msg.folders){
	add_to_folders(msg);
}
//拷贝赋值函数 -->执行拷贝构造和析构
Message& Message::operator=(const  Message& msg) {
	remove_from_folders();
	contents = msg.contents;
	folders = msg.folders;
	add_to_folders(msg);
	return *this;
}
Message::~Message() {
	remove_from_folders();
}

//使用swap完成不必要的拷贝
void Message::swap(Message& lhs, Message& rhs) {
	using std::swap;
	for (auto f : lhs.folders) {
		f->remMsg(&lhs); //从folders删除本Msg
	}
	for (auto f : rhs.folders) {
		f->remMsg(&rhs); //从folders删除本Msg
	}
	swap(lhs.contents, rhs.contents);
	swap(lhs.folders, rhs.folders);
	for (auto f : lhs.folders) {
		f->addMsg(&lhs); 
	}
	for (auto f : rhs.folders) {
		f->addMsg(&rhs); 
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34269988/article/details/88760925