关于C++ 0x的右值引用
2013-01-28 本文已影响148人
剑舞春秋
右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践角度讲,它能够完美解决C++中长久以来为人所诟病的临时对象效率问题。从语言本身讲,它健全了C++中的引用类型在左值右值方面的缺陷。从库设计者的角度讲,它给库设计者又带来了一把利器。从库使用者的角度讲,不动一兵一卒便可以获得“免费的”效率提升…
右值引用
在C++03中,临时变量(右值,出现在等号右侧的变量。另一种解释是引用值,没有实际地址的值)和const & type没有实际的差别。而在C++0X标准中添加了一种新的引用类型。叫做右值引用。它的定义类似于typename &&。另外右值引用提供了一种转移语义。
C++代码块:
#include <stdio.h>
#include <tchar.h>
#include <vector>
#include <iostream>
using
namespace
std;
class
ObjA
{
public
:
ObjA():data(NULL)
{
cout<<_T(
"调用构造函数"
)<<endl;
}
ObjA(
const
char
*_data)
{
int
Len=
strlen
(_data);
data=
new
char
[Len];
memcpy
(data,_data,Len);
cout<<data<<endl;
cout<<_T(
"调用带参构造函数 memcpy"
)<<endl;
}
~ObjA()
{
if
(data)
{
cout<<data<<endl;
delete
[] data;
data=NULL;
cout<<
"delete memory data"
<<endl;
}
cout<<_T(
"调用析构函数."
)<<endl;
}
//拷贝赋值
ObjA& operator=(
const
ObjA &b)
{
int
Len=
strlen
(b.data);
data=
new
char
[Len];
memcpy
(data,b.data,Len);
cout<<_T(
"调用operator = 函数. memcpy"
)<<endl;
return
*
this
;
}
ObjA(
const
ObjA &b)
{
cout<<_T(
"调用拷贝构造函数. memcpy"
)<<endl;
if
(
this
!=&b)
{
int
Len=
strlen
(b.data);
data=
new
char
[Len];
memcpy
(data,b.data,Len);
}
}
//Move拷贝构造函数
ObjA(ObjA &&b)
{
cout<<
"Move拷贝构造函数"
<<endl;
if
(
this
!=&b)
{
data=b.data;
b.data=NULL;
}
}
//Move赋值拷贝
ObjA& operator=(ObjA &&b)
{
cout<<_T(
"Move operator = 函数."
)<<endl;
if
(
this
!=&b)
{
data=b.data;
b.data=NULL;
}
return
*
this
;
}
char
*data;
};
ObjA testRValue_ChangeStr(ObjA o)
{
delete
[] o.data;
char
*tmp=
"string after change"
;
int
Len=
strlen
(tmp);
o.data=
new
char
[Len];
memcpy
(o.data,tmp,Len);
return
o;
}
int
_tmain(
int
argc, _TCHAR* argv[])
{
//实现了Move拷贝和Move赋值函数.即只移动内部指针,不移动数据.
ObjA a(
"obj A"
);
ObjA b(
"obj B"
);
b=testRValue_ChangeStr(a);
//由于text...函数返回的是个临时对象,即右值
//所以ObjA的 ObjA& operator=(ObjA &&b)函数被调用.
//b Move拷贝了testRVa...函数返回的临时对象的数据.
//test vector
vector<ObjA> *v=
new
vector<ObjA>;
//push_back每调用一次,就会调用Move拷贝构造函数
//把旧内存里的对象移至新分配的内存里去.
v->push_back(*
new
ObjA(
"C"
));
v->push_back(*
new
ObjA(
"D"
));
v->push_back(*
new
ObjA(
"E"
));
//以上总共调用了三次memcpy函数,移动数据
return
0;
}