在c++11中,支持右值引用,右值引用的用处之一是移动语义,对象的资源所有权发生转移,在c++11之前,移动语义的缺失是c++饱受诟病的问题之一.
什么是左值?什么是右值?
凡有名者,皆为左值.左值对应变量的存储位置,右值对应变量的值本身,右值可以被赋值给左值,或者绑定到引用.
右值引用的优点?
类的右值是一个临时对象,如果没有被绑定到引用,在表达式结束时候,就会废弃,在右值被废弃之前,移走资源进行废物利用.
被移走资源的右值在废弃时已经成为空壳,析构的开销降低.
为临时变量续命,也就是为右值续命,右值在表达式结束后就消亡了,如果想继续使用右值,就会使用昂贵的拷贝构造函数
如果能够直接使用临时对象已经申请的资源,既能节省资源,又能节省资源申请和释放的时间
看一个具体的例子:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class TestString
{
private:
char *data_;
size_t len_;
void _init_data(const char *p)
{
data_ = new char[len_ + 1];
memcpy(data_, p, len_);
data_[len_] = '\0';
}
public:
TestString()
{
data_ = NULL;
len_ = 0;
}
TestString(const char *p)
{
len_ = strlen(p);
_init_data(p);
}
TestString(const TestString &str)
{
len_ = str.len_;
_init_data(str.data_);
std::cout << "Copy Structor is called! source:" << str.data_ << std::endl;
}
TestString& operator=(const TestString &str)
{
if(this != &str)
{
len_ = str.len_;
_init_data(str.data_);
}
std::cout << "Copy Assignment is called! source:" << str.data_ << std::endl;
return *this;
}
//TestString(TestString &&str)
//{
// std::cout << "Move Constructor is called! source:" << str.data_ << std::endl;
// len_ = str.len_;
// data_ = str.data_;
// str.len_ = 0;
// str.data_ = NULL;
//}
//TestString& operator=(TestString &&str)
//{
// std::cout << "Move Assignment is called! source:" << str.data_ << std::endl;
// if(this != &str)
// {
// len_ = str.len_;
// data_ = str.data_;
// str.len_ = 0;
// str.data_ = NULL;
// }
// return *this;
//}
virtual ~TestString()
{
if(data_)
{
delete []data_;
data_ = NULL;
}
}
};
int main(int argc, char *argv[])
{
TestString a;
a = TestString("Hello ");
std::vector<TestString> vec;
vec.push_back(TestString(" Wrold"));
return 0;
}
说明两点:
(1)左值引用符号&,右值引用符号&&,右值引用符号只有在c++11中才被支持;
(2)程序中的注释部分,包含右值引用拷贝构造函数和右值引用赋值构造函数,取消注释前后程序的运行结果不一致,可以体会一下右值引用的含义,以及移动语义的优点: