左值与右值的定义
C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值。通俗的左值的定义就是非临时对象,那些可以在多条语句中使用的对象。
所有的变量都满足这个定义,在多条代码中都可以使用,都是左值。右值是指临时的对象,它们只在当前的语句中有效(比如立即数,未命名对象)
//注意 考虑到安全因素,具名变量即使被声明为右值类型也不会被当作右值 而要用std::move函数(以下说明)
右值引用 实现了 语意转移 和 完美转发
语意转移 std::move
用途 没有了无意义的拷贝工作,效率大大提升
编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对它调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用,怎么做呢?标准库提供了函数 std::move,这个函数以非常简单的方式将左值引用转换为右值引用。
示例1
string str_1 = "123";
string s(std::move(str_1));/*str_1被转移构造到了s*/ //string(&&)
//string s2(str_1);/*拷贝构造函数*/ //string(string&)
std::cout << s << endl;;/*123*/
cout << str_1 << endl;/*str_1已被转移 所以为空*/
示例2
#include<iostream>
#include "vector"
#include "string"
#include "functional"
#include "windows.h"
using namespace std;
class _string
{
public:
char*_data;
void alloc()
{
_data = (char*)malloc(sizeof(char)* 100);
}
_string&operator=(const char*s)
{
cout << "call =const char*" << endl;
strcpy(_data, s);
return *this;
}
_string &operator=(const _string& s)
{
cout << "call = const string&" << endl;
strcpy(_data, s.c_str());
return *this;
}
_string &operator=(_string&&s)
{
cout << "call =string&&" << endl;
this->_data = s._data;
s._data = 0;
return *this;
}
_string(_string&&s)
{
cout << "call string string &&" << endl;
this->_data = s._data;
s._data = 0;
}
_string(_string&s)
{
alloc();
cout << "call string string &" << endl;
strcpy(_data, s.c_str());
}
_string(const char*s)
{
alloc();
cout << "call string const char*" << endl;
strcpy(_data, s);
}
_string(const _string&s)
{
alloc();
cout << "call string const string &" << endl;
strcpy(_data, s.c_str());
}
_string()
{
alloc();
cout << "call string" << endl;
strcpy(_data, "\0");
}
~_string()
{
if (_data)
{
cout << "call ~_stirng with free" << endl;
free(_data);
return;
}
cout << "call ~_stirng" << endl;
}
const char* c_str() const
{
return (const char*)_data;
}
};
_string func()
{
_string str = "65546465";
//return str;
return std::move(str);
}
int main()
{
//{
_string&& s = (func());
//}
system("pause");
return 0;
}