C++Primer 第十三章13.6对象移动,移动构造函数,移动赋值运算符。

本文详细解读了C++中Message类的移动构造函数、移动赋值运算符和StrVec类的移动构造与移动赋值,展示了如何在对象生命周期结束前高效转移资源。涉及类的设计与内存管理优化。

又回来看对象移动了。。。

Message类的移动成员


Message& Message::operator=(const Message& m)
{
	if (this != &m)
	{
		remove_from_Folders();
		Folders = m.Folders;
		contents = m.contents;
		add_to_Folders(m);
	}
	return *this;
}

Message& Message::operator=(Message&& Msg)
{
	// 移动赋值运算符
	
	// error
	//if (this != &Msg)
	//{
	//	remove_from_Folders();
	//	Folders = Msg.Folders;
	//	contents = std::move(Msg.contents);
	//	add_to_Folders(Msg);
	//}
	// error

	if (this != &Msg)
	{
		remove_from_Folders();
		contents = std::move(Msg.contents);
		move_Folders(&Msg);
	}
	return *this;
}

void Message::move_Folders(Message* m)
{
	Folders = std::move(m->Folders);
	for (auto& f : Folders)
	{
		f->addMsg(this);
		f->removeMsg(m);
	}
	m->Folders.clear();
}

Message::Message(Message&& Msg) : contents(std::move(Msg.contents))
{
	move_Folders(&Msg);
}

Message类是什么:C++ Primer 第十三章 13.4 拷贝控制示例 Message类+Folder类_配的上了吗的博客-优快云博客

其实,Message就是一条消息,主要的数据成员是一个string contents  而对应的是一个Folder类,Folder类里面有个set<Message*> Msgs; 也就是一个消息列表样的东西。

移动构造函数和移动赋值运算符的参数都是一个右值引用类型,代表着,这个引用所指向的对象即将删除,可以从此对象中窃取信息,所以,移动构造函数和移动赋值运算符都需要将参数从对应的消息列表中删除,并且在消息列表中添加这个新的消息。所以创建了一个move_Folder函数来完成这个功能。首先利用set的移动赋值运算符,将参数的set移动过去,移动之后参数的已经为空了。之后对于Folders中的每一个Folder*成员都调用函数将原来的消息删除,并添加新的消息。最后保险起见再把参数的Folders成员置为空。

移动构造函数非常简单,将contents移动过去,这里调用的是string的移动构造函数。然后将Folders成员处理一下即可。

StrVec类的移动构造函数和移动赋值运算符

StrVec::StrVec(StrVec&& v) noexcept 
	:elements(v.elements), first_free(v.first_free), cap(v.cap)
{
	// 移动构造函数
	v.elements = v.first_free = v.cap = nullptr;
}

StrVec& StrVec::operator=(StrVec&& v) noexcept
{
	if (this != &v)
	{
		free();
		elements = v.elements;
		first_free = v.first_free;
		cap = v.cap;
		v.elements = v.first_free = v.cap = nullptr;
	}
	return *this;
}

有关StrVec类是什么:C++ Primer 第十三章 13.5 动态内存管理类 类StrVec_配的上了吗的博客-优快云博客

这个是比较简单的,就是,从右值引用那里把资源接管过来,然后将参数置为一种可析构的状态即可。移动赋值运算符同样需要考虑自赋值的情况。 

StrVec类的两个push_back成员,参数分别为const的左值引用,和右值引用。

void StrVec::push_back(const string& s)
{
	chk_n_alloc();  // 确保有空间可以进行构造
	alloc.construct(first_free++, s);  // 在first_free指向的元素中构造s的副本
	// 会根据参数确定用哪个构造函数来构造对象,本例中只有一个额外参数,类型为string,因此会使用string的拷贝构造函数
}

void StrVec::push_back(string&& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, std::move(s));
}

 

 当传递的是一个左值时,是无法匹配右值引用版本的push_back的,所以会调用const string& 参数的push_back。而传递一个临时对象,即右值时,string&&是精确匹配,虽然可以将其转化为const string& 但这是多余的行为,所以会匹配参数为string&&类型的push_back

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值