c11右值与移动语义
左值和右值:
左值具名,对应指定内存域,可访问;右值不具名,不对应内存域,不可访问;
临时对像是右值,左值可处于等号左边,右值只能放在等号右边,区分表达式的左右值属性有一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。
右值引用:
在 C++11 之前,右值是不能被引用的,最大限度就是用常量引用绑定一个右值,如 :const int &a = 1; 在这种情况下,右值不能被修改的。但是实际上右值是可以被修改的,既然右值可以被修改,那么就可以实现右值引用。C11增加的右值引用类型T &&,就是为了解决这一问题。
右值引用的作用:右值引用是用来支持转移语义的。转移语义可以将资源 ( 堆,系统对象等 ) 从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,能够大幅度提高 C++ 应用程序的性能。消除了临时对象的维护 ( 创建和销毁 ) 对性能的影响。
避免无意义复制
析构开销减少
当类的拷贝构造函数入参是右值时,可以避免复制和析构:
class A
{
public:
A() :m_ptr(new int(0)){}
A(const A& a):m_ptr(new int(*a.m_ptr)) //深拷贝的拷贝构造函数
{
cout << "copy construct" << endl;
}
A(A&& a) :m_ptr(a.m_ptr)
{
a.m_ptr = nullptr;
cout << "move construct" << endl;
}
~A(){ delete m_ptr;}
private:
int* m_ptr;
};
int main(){
A a = Get(false);
}
引用折叠
引用折叠。通常,我们不能直接定义一个引用的引用,但是同过类型别名(使用typedef)和模板间接定义是可以的。当定义了引用的引用时,则这些引用形成了“折叠”,所有的情况下(除了一个例外),引用会折叠成一个普通的左值引用类型。这个例外就是右值引用的右值引用:
l X& &&、X& &&、X&& &都折叠成X&
l 类型X&& &&折叠成X&&
std::move
move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。
std::list< std::string > tokens;//省略初始化...
std::list< std::string > t = tokens; //存在拷贝
std::list< std::string > t2 = std::move(tokens); //不存在拷贝
如果不用std::move,拷贝的代价很大,性能较低。使用move几乎没有任何代价,只是转换了资源的所有权。如果一个对象内部有较大的对内存或者动态数组时,很有必要写move语义的拷贝构造函数和赋值函数,避免无谓的深拷贝,以提高性能。
std::forward
完美转发(perfect forwarding),是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。std::forward即是为转发而生,它会按照参数本来的类型来转发出去,不管参数类型是T&&这种未定的引用类型还是明确的左值引用或者右值引用。
上一篇: 单层神经网络(感知器)的python实现
下一篇: 神经网络(单层感知器)
推荐阅读
-
c11右值与移动语义
-
《深入理解C++11:C++ 11新特性解析与应用》——3.3 右值引用:移动语义和完美转发...
-
cpp const引用和右值引用的区别,std::move(移动语义), std::forward(完美转发)
-
C++雾中风景10:聊聊左值,纯右值与将亡值
-
c/c++ 拷贝控制 右值与const引用
-
深入了解c++11 移动语义与右值引用
-
浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析,左值与右值
-
C++11 右值引用和移动语义
-
C++ 拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符、析构函数、右值引用、引用限定符实例
-
左值与右值在C++标准中的表述