语义相关

发布时间 2023-04-09 13:13:06作者: MyXjl

值语义

指目标对象由源对象拷贝生成,且生成后与源对象完全无关,彼此独立存在,改变互不影响,就像int类型互相拷贝一样。C++的内置类型(bool/int/double/char)都是值语义,标准库里的complex<> 、pair<>、vector<>、map<>、string等等类型也都是值语意,拷贝之后就与原对象脱离关系。C++中基于值语义的拷贝构造和赋值拷贝,会招致对资源密集型对象不必要拷贝,大量的拷贝很可能成为程序的性能瓶颈。

对象语义

对象语义就是只有一个对象,不支持拷贝复制等操作。

移动语义

  • 左值引用,使用T&,只能绑定左值
  • 右值引用,使用T&&,只能绑定右值
  • 常量左值引用,使用const T&,既可以绑定左值,又可以绑定右值,但是不能对其进行修改

移动语义不是试图取代复制语义,也不是以任何方式破坏它。相反,该提议旨在增强复制语义。

移动语义主要是性能优化:将昂贵的对象从内存中的一个地址移动到另外一个地址的能力,同时窃取源资源以便以最小的代价构建目标。

在C++11之前,当进行值传递时,编译器会隐式调用拷贝构造函数;自C++11起,通过右值引用来避免由于拷贝调用而导致的性能损失。

右值引用的主要用途是创建移动构造函数和移动赋值运算符。移动构造函数可以避免内存重新分配,这是因为移动构造函数的参数是一个右值引用,也可以说是一个临时对象,而临时对象在调用之后就被销毁不再被使用,因此,在移动构造函数中对参数进行移动而不是拷贝。换句话说,右值引用移动语义允许我们在使用临时对象时避免不必要的拷贝。

// 移动构造函数
String(String &&rhs)
: _pstr(rhs._pstr)
{
	rhs._pstr = nullptr;
}

// 移动赋值运算符函数
String& operator=(String&& rhs)
{
	if(this != rhs)
	{
		delete [] _pstr;		// 释放左操作数
		_pstr = rhs._pstr;		// “移动”所有权
		rhs._pstr = nullptr;	// 避免临时对象的析构函数将资源释放掉
	}
	
	return *this;
}