移动语义

std::vector<String> v;
v.push_back(“string”);
调用 String::String(const char *);
调用 String::String(const String&);
调用 String::~String()
问题症结在于,临时对象的构造和析构带来了不必要的资源拷贝

如果有一种机制,可以在语法层面识别出临时对象,在使用临时对象构造新对象(拷贝构造)的时候,将临时对象所持有的资源『转移』到新的对象中,就能消除这种不必要的拷贝。

根据其修饰符的不同,可分为非常量左值引用和常量左值引用

int ia = 10;       int &a = ia;
const int ib = 30; int &b = ib;
const int &ri = 20;

非常量左值引用只能绑定到非常量左值
常量左值引用可以绑定到所有类型的值,包括  非常量左值、常量左值、右值(根据语法规则,无法区分出右值)

编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对它调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用,怎么做呢?标准库提供了函数 std::move,这个函数以非常简单的方式将左值引用转换为右值引用。

当存在移动语义时,会优先调用

talk  is cheap,Let‘s code

 ///
 /// @file    String.cc
 /// @author  miaobeihai(452686191@qq.com)
 /// @date    2017-05-02 09:45:30
 ///
 
#include <string.h>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;


class String
{
public:
	String()
	: _pstr(new char[1])
	{
		cout << "String()" << endl;
		_pstr[0] = '\0';
	}

	String(const char * pstr)
	: _pstr(new char[strlen(pstr) + 1])
	{
		cout << "String(const char *)" << endl;
		strcpy(_pstr, pstr);
	}

	//移动构造函数
	String(String && rhs)//右值引用只能绑定到右值
	: _pstr(rhs._pstr) 
	{
		cout << "String(String && rhs)" << endl;
		rhs._pstr = NULL;
	}

	//复制构造函数
	String(const String & rhs) //形参const引用能绑定到左值或者右值上,
							   //意味着它不能区分出传递过来的实参是
							   //左值还是右值;为了达到转移临时对象的内容,
							   //需要新的语法规则能在语法层面识别出右值,
							   //所以C++11中引入了右值引用,右值引用只能绑定到右值
	: _pstr(new char[strlen(rhs._pstr) + 1])
	{
		cout << "String(const String&)" << endl;
		strcpy(_pstr, rhs._pstr);
	}


	//移动赋值运算符 
	String & operator=(String && rhs)
	{
		cout << "String & operator=(String && rhs)" << endl;
		if(this != & rhs)
		{
			delete [] _pstr;
			_pstr = rhs._pstr;

			rhs._pstr = NULL;
		}
		return *this;
	}

	String & operator=(const String & rhs)
	{
		if(this != &rhs)
		{
			delete [] _pstr;

			_pstr = new char[strlen(rhs._pstr) + 1];
			strcpy(_pstr, rhs._pstr);
		}
		return *this;
	}

	~String()
	{
		cout << "~String()" << endl;
		delete [] _pstr;
	}

	friend std::ostream & operator<<(std::ostream & os, const String & rhs);
private:
	char * _pstr;
};

std::ostream & operator<<(std::ostream & os, const String & rhs)
{
	os << rhs._pstr;
	return os;
}

int main(void)
{
	String s1("hello");
	cout << "s1 = " << s1 << endl;

	String s2 = std::move(s1);//move函数显示地将左值引用转换成右值引用
	cout << "s2 = " << s2 << endl;

	cout << "s1 = " << s1 << endl;

	return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值