13.4 拷贝控制示例

13.33:为什么Message的成员save和remove的参数时一个Folder &?为什么我们不将参数定义为Folder或是const Folder &?

成员内部调用的函数需要改变Folder中的元素,Folder或是const Folder &都无法做到。

13.34:编写本节所描述的Message。

class Folder;
class Message {
	friend void swap(Message &, Message &);
	string contents;
	set<Folder*> folders;
	void add_to_Folders(const Message &);
	void remove_form_Folders();
public:
	explicit Message(const string &str = "") :contents(str) {}
	Message(const Message &);
	~Message();
	Message & operator = (const Message &);
	void save(Folder &);
	void remove(Folder &);
};
void swap(Message &, Message &);//声明
//容器set内部会构造指针的副本
Message::Message(const Message &msg) :contents(msg.contents), folders(msg.folders) {
	add_to_Folders(msg);
}
Message::~Message() {
	remove_form_Folders();
}
Message &  Message::operator = (const Message &msg) {
	remove_form_Folders();
	contents = msg.contents;
	folders = msg.folders;//容器set内部会构造指针的副本
	add_to_Folders(msg);//将本消息添加到指向msg的所有Folder中
	return *this;
}
void Message::save(Folder &fd) {
	folders.insert(&fd);
	fd.addMsg(this);
}
void Message::remove(Folder &fd) {
	folders.erase(&fd);
	fd.remMsg(this);
}
void Message::add_to_Folders(const Message &msg) {
	for (auto f : msg.folders)
		f->addMsg(this);
}
void Message::remove_form_Folders() {
	for (auto f : folders)
		f->remMsg(this);
}
void swap(Message &lhs, Message &rhs) {
	using std::swap;
	for (auto f : lhs.folders)
		f->remMsg(&lhs);
	for (auto f : rhs.folders)
		f->remMsg(&rhs);
	swap(lhs.folders, rhs.folders);
	swap(lhs.contents, rhs.contents);
	for (auto f : lhs.folders)
		f->addMsg(&lhs);
	for (auto f : rhs.folders)
		f->addMsg(&rhs);
}

13.35:如果Message使用合成版本的拷贝控制成员,将会发生什么?

当拷贝一个Message时,副本的指针将不会出现在任何一个Folder中(尽管它包含了其所在Folder的指针set)。更严重的,当某Message析构后,其所在Folder中任然保留了该Message的指针,该指针是无效的!

13.36:设计并实现对应的Folder类。此类应该保存一个指向Folder中包含的Message的set。

class Folder {
	set<Message*> messages;
public:
	void addMsg(Message *const pMsg) { messages.insert(pMsg); }
	void remMsg(Message *const pMsg) { messages.erase(pMsg); }
};


13.37:为Message类添加成员,实现向folders添加或删除一个给定的Folder*。这两个成员类似Folder类的addMsg和remMsg操作。

class Message {
	//其余成员
	void addFolder(Folder *const fd) { folders.insert(fd); }
	void remFolder(Folder *const fd) { folders.erase(fd); }
};

13.38:我们并未使用拷贝并交换方式来设计Message的赋值运算符。你认为原因是什么?

如459页所示,使用swap设计的赋值运算符采用的是值传递的方式传递参数,会引起Message中整个set的拷贝;更重要的是,尽管只是值传递,但是swap仍然会更新到运算符右侧的Message的folders,这显然不是我们所希望的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值