http://www.cnblogs.com/soaliap/archive/2012/11/19/2777131.html
主要是两个问题
返回优化
vector<SpecialClass>&& func()
{ …
return std::move(vect); //move,取得一个左值的右值
}
复制省略
在类里实现转移构造函数
一:第一个具有const引用的函数,可以接受任意的参数,不管是左值还是右值,不管这个左值或者右值易变或者不易变(if mutable);但是对于第二个函数,除了mutable rvalue-references类型,其他的类型都可以。
二:先从例子入手
printReference (constString& str)
{
cout << str;
}
printReference (String&& str)
{
cout << str;
}
第一个具有const引用的函数,可以接受任意的参数,不管是左值还是右值,不管这个左值或者右值易变或者不易变(if mutable);但是对于第二个函数,除了mutable rvalue-references类型,其他的类型都可以
- class ArrayWrapper
- {
- public:
- ArrayWrapper (int n)
- : _p_vals( new int[ n ] )
- , _size( n )
- {}
- // copy constructor
- ArrayWrapper (const ArrayWrapper& other)
- : _p_vals( new int[ other._size ] )
- , _size( other._size )
- {
- for ( int i = 0; i < _size; ++i )
- {
- _p_vals[ i ] = other._p_vals[ i ];
- }
- }
- ~ArrayWrapper ()
- {
- delete [] _p_vals;
- }
- private:
- int *_p_vals;
- int _size;
- };
- class ArrayWrapper
- {
- public:
- // default constructor produces a moderately sized array
- ArrayWrapper ()
- : _p_vals( new int[ 64 ] )
- , _size( 64 )
- {}
- ArrayWrapper (int n)
- : _p_vals( new int[ n ] )
- , _size( n )
- {}
- // move constructor
- ArrayWrapper (ArrayWrapper&& other)
- : _p_vals( other._p_vals )
- , _size( other._size )
- {
- other._p_vals = NULL;
- }
- // copy constructor
- ArrayWrapper (const ArrayWrapper& other)
- : _p_vals( new int[ other._size ] )
- , _size( other._size )
- {
- for ( int i = 0; i < _size; ++i )
- {
- _p_vals[ i ] = other._p_vals[ i ];
- }
- }
- ~ArrayWrapper ()
- {
- delete [] _p_vals;
- }
- private:
- int *_p_vals;
- int _size;
- };
==================================================================================
简介
C++0X是新一代C++标准的非官方名称。它将代替C++03成为C++最新的标准。C++0X对C++的核心语言以及标准库经进行了部分更新。C++0X完全兼容目前的C++标准。
在C++0X之中,语言本身添加了对于多线程的支持。一些细节得到了改进,例如支持统一初始化方式。对泛型编程的支持方面有了更边界的,同时对功能进行了改进。
核心语言功能
右值引用
在C++03中,临时变量(右值,出现在等号右侧的变量。另一种解释是引用值,没有实际地址的值)和const & type没有实际的差别。而在C++0X标准中添加了一种新的引用类型。叫做右值引用。它的定义类似于typename &&。另外右值引用提供了一种转移语义。
动机
右值引用的出现使得一些基础概念或者effective C++中表述的一些条目需要重新编写。那么来看看右值引用出现的动机是什么。
来看一个例子
std::vector实际上内部就是一个C类型数组,并且提供了一些内存和性能优化管理的机制。那么在现行的C++03标准中,当一个vector临时变量或者函数返回一个vector类型对象的时候。这里无可避免、毫无疑问的将会产生一个新的vector变量,并且将所有右值中的成员变量拷贝到这个临时变量中。(当然有些编译器具有NRV的优化功能,但是这种优化功能的执行情况和在复杂函数中的优化效果值得商榷)并且在拷贝结束后这个临时变量将被销毁,完成它短暂而又神圣的使命。
vector<SpecialClass> func()
{
…
return vect;
}
使用右值引用,在以上场景中std::vector的转移构造函数会被调用。转移的过程是把右值vector中指向C类型数组的指针直接拷贝到新的vector对象中。然后把右值中的数组指针置空。这样就省去了数组拷贝过程,并且删除一个空的临时变量不会产生大量的内存操作。
那么我们需要将返回值声明为std::vector<>&&,将会大幅简化内存操作。
vector<SpecialClass>&& func()
{
…
return std::move(vect);
}
右值引用不能引用一个左值对象,为了可以对指定的左值对象进行右值引用操作。标准库提供了std::move()函数。通过该函数可以获得指定对象的左值。
为自己的类定制右值引用构造函数
SpecialClass(SpecialClass&& rhs)
{
…
return *this;
}
当调用右值引用的类并没有定义右值引用构造函数时,默认的拷贝构造函数会被调用,并且参数会以const &的形式传入。
为了便于在模板中进行参数推到,标准库提供了std::forward()函数通过此函数可以保证传入参数的左右值性质不变
template <class T, class A1>
inline
shared_ptr<T>
factory(A1&& a1)
{
// If a1 is bound to an lvalue, it is forwarded as an lvalue
// If a1 is bound to an rvalue, it is forwarded as an rvalue
return shared_ptr<T>(new T(forward<A1>(a1)));
}
struct A
{
...
A(const A&); // lvalues are copied from
A(A&&); // rvalues are moved from
};
int main()
{
A a;
shared_ptr<A> sp1 = factory<A, A>(a); // "a" copied from
shared_ptr<A> sp2 = factory<A, A>(move(a)); // "a" moved from
}