C++11 新标准(六)

来源:互联网 发布:大数据来源 编辑:程序博客网 时间:2024/05/19 14:35
1.左值与右值的区别:左值能够对该表达式取地址(如变量名或对象名)
2.右值引用:
T k = getVar() //getVar()为右值,结束时被销毁T&& k = getVar() //getVar()使用了右值引用,结束时不会被销毁,生命周期和k相同
3.关于右值引用一个有意思的问题是:T&&是什么,一定是右值吗?让我们来看看下面的例子:
template<typename T>void f(T&& t){}f(10); //t是右值int x = 10;f(x); //t是左值
从上面的代码中可以看到,T&&表示的值类型不确定,可能是左值又可能是右值,这一点看起来有点奇怪,这就是右值引用的一个特点
T&& t在发生自动类型推断的时候,它是未定的引用类型(universal references),如果被一个左值初始化,它就是一个左值;如果它被一个右值初始化,它就是一个右值,它是左值还是右值取决于它的初始化
4.
(1)非const左值引用只能绑定到非const左值;
(2)const左值引用可绑定到const左值、非const左值、const右值、非const右值;
(3)非const右值引用只能绑定到非const右值;
(4)const右值引用可绑定到const右值和非const右值。
5.移动构造函数
(1)深度拷贝虽然安全,但性能消耗大,对于右值,可以考虑用浅复制,即使用移动构造函数(或移动赋值函数)
(2)一个使用移动构造函数的例子:
A(A&& a):ptr(a.ptr){a.ptr = nullptr;}
因为A&& a只接受左值,即临时值,因此只要做到浅复制即可
注意:一般提供移动构造函数时同时提供拷贝构造函数,避免移动不成功
(3)我们知道移动语义是通过右值引用来匹配临时值的,那么,普通的左值是否也能借助移动语义来优化性能呢?

普通左值可以通过std::move()将左值转化为右值

//不使用move语义,使用拷贝构造函数list<string> temp;temp = a;a = b;b = temp;//使用move,转换构造函数list<string> temp;temp = move(a);a = move(b);b = move(temp);

(4)一个要注意的情况是,拷贝构造函数中可以使用*this = s,而move构造函数中不能这么使用,但是,可以借用move赋值函数:*this = move(s)
6.完美转发
C++11中的std::forward()可以按照实际情况进行转发

void processValue(int& a){cout << "l_reference" << endl;}void processValue(int&& a){cout << "r_reference" << endl;}template <typename T>void forwardValue(T&& value)//在这里,T&&右值引用为一个universal reference,可接受左右引用,因此可以作为参数路由{processValue(forward<T>(value));}void test(){int i = 0;forwardValue(0);forwardValue(i);}/*输出结果为:r_referencel_reference */

7.万能的函数包装器

右值引用、完美转发再结合可变模板参数,我们可以写一个万能的函数包装器,它可以接收所有的函数,带返回值的、不带返回值的、带参数的和不带参数的函数都可以委托这个万能的函数包装器执行。看看这个万能的函数包装器

//万能函数包装器:template <class Function, class...Args> inline auto FunctionWrap(Function&& f,Args&& ...args)->decltype(f(std::forward<Args>(args)...)){return f(std::forward<Args>(args)...);}


//应用实例:#include <iostream>using namespace std;template <class Function, class...Args> inline auto FunctionWrap(Function&& f,Args&& ...args)->decltype(f(std::forward<Args>(args)...)){return f(std::forward<Args>(args)...);}void test0(){cout << "void\n";}int test1(){return 1;}int test2(int i){return i;}string test3(string a,string b){return a + b;}int main(){FunctionWrap(test0);cout << FunctionWrap(test1) << endl;cout << FunctionWrap(test2,2) << endl;cout << FunctionWrap(test3,"Good","Bad") << endl;}

8.容器的成员函数emplace_back
c++11中大部分容器都加了一个emplace_back成员函数,vector中它的定义是这样的:
template< class... Args >
void emplace_back( Args&&... args );
这里的Args&&是一个未定的引用类型,因此它可以接收左值引用和右值引用,它的内部也是调用了std::forward实现完美转发的。因此如果我们需要往容器中添加右值、临时变量时,用emplace_back可以提高性能


0 0
原创粉丝点击