std::move做了什么?

std::move将对象标记为可变的右值对象。根据引用折叠原则,std::move的参数可以为右值引用,那么这个函数将什么都不做。

std::move的实现非常简单暴力:


namespace std
{

	template<typename T>
	struct CRemoveReference
	{
		using Type = T;
	};

	template<typename T>
	struct CRemoveReference<T&>
	{
		using Type = T;
	};

	template<typename T>
	struct CRemoveReference<T&&>
	{
		using Type = T;
	};

	template<typename T>
	using remove_reference_t =typename CRemoveReference<T>::Type;
	
	template<typename T>
	constexpr remove_reference_t<T>&& move(T&& t) noexcept
	{
		return static_cast<remove_reference_t<T>&&>(t);
	}

}

右值的作用是什么呢?

为了更好的避免内存(尤其是大内存)拷贝和冗余式地释放和申请,允许类设计者通过定义移动拷贝构造函数/移动赋值运算符函数。

A a1;
A a2 = std::move( a1 );
a1 = std::move(a2);

第二行语句将执行移动拷贝构造(move constructor):

  1. 创建一片大小为sizeof(A)的内存;
  2. 将a1中 内容拷贝到这片内存中;
  3. a1中的有效内存被销毁。

 注意:如果不自定义move-constructor,那么将调用默认的copy-constructor。如果对象中有堆内存管理,必须定义move-constructor。

第三句将执行移动赋值运算符(move assigment operator)函数。

下面的例子:

test函数中的

  • 第一个语句,相当于a调用构造函数创建了一个对象;
  • 第二个语句,在getA2中创建了一个临时对象,又调用A的move-constructor创建了b,再销毁了临时对象.
  • 第三个语句,会强制进行move-constructor,整体同语句2
  • 第四个语句,std::move的参数如果是A&& ,则相当于什么都不做,所以和语句2相同。
A getA1( )
{
    return A();
}
A getA2( )
{
    A a;
    a.x = 123;
    a.y = 456;
}
void test( )
{
    A a = getA1( );
    A b = getA2( );
    A a = std::move( getA1( ) );
    A b = std::move( getA2( ) );
}

自定义move-constrctor和move-assigment-operator样例


struct Thing
{
	Thing( )noexcept : 
		_data(new int[100])
	{
		std::cout << "default construct\n";

	}

	// Copy operator
	Thing(const Thing& other)noexcept :
		_data(new int[100]) 
	{
		std::cout << "copy constructor\n";
		memcpy(_data, other._data, sizeof(int) * 100);
	}

	// Move constructor
	Thing(Thing&& other) noexcept :
		_data(other._data)
	{
		std::cout << "move constructor\n";
		other._data = nullptr;
	}

	// assignment operator
	Thing& operator=(const Thing& rhs) noexcept 
	{
		std::cout << "copy operator\n";
		if (&rhs != this) 
		{
			Thing tmp(rhs);
			std::swap(*this, tmp);
		}
		return *this;
	}

	// move assignment operator
	Thing& operator=(Thing&& rhs) noexcept 
	{
		std::cout << "move operator\n";
		std::swap(_data, rhs._data);
		return *this;
	}


	// destructor necessary since we are working in dangerous new/delete territory
	~Thing() noexcept
	{
		std::cout << "destructor " << (_data ? "object has data" : "object is empty") << "\n";

		delete[] _data;
	}
private:
	int* _data;
};
int main2()
{
	std::cout << "constructing a\n";
	Thing a;

	std::cout << "constructing b with copy of a\n";
	Thing b(a);

	std::cout << "moving a to newly constructed c\n";
	Thing c(std::move(a));

	std::cout << "moving c back to a\n";
	a = std::move(c);

	std::cout << "create a new d\n";
	Thing d;
	std::cout << "replace d with a copy of a\n";
	d = a;

	return 0;
}

输出:

constructing a
default construct
constructing b with copy of a
copy constructor
moving a to newly constructed c
move constructor
moving c back to a
move operator
create a new d
default construct
replace d with a copy of a
copy operator
copy constructor
move constructor
move operator
move operator
destructor object is empty
destructor object has data
destructor object has data
destructor object is empty
destructor object has data
destructor object has data

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值