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

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

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

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类_配的上了吗的博客-CSDN博客

其实,Message就是一条消息,主要的数据成员是一个string contents  而对应的是一个Folder类,Folder类里面有个set 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_配的上了吗的博客-CSDN博客

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

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

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1330489.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-12
下一篇2022-06-12

发表评论

登录后才能评论

评论列表(0条)

    保存