c++| c++11左右值引用,完美转发,可变参数模板

左,右值引用

什么是左值,右值

左右值的语法上的区别就是能不能取地址。
int a = 10; a 可以取地址 是左值, 但是 10不能取地址 是右值。
常见的右值还有匿名对象,表达式返回值,字面常量(就是直接写出来的值比说刚刚的10)等。

左值引用和右值引用

左值引用 T &val , 右值应用 T&& val
一般的左值引用,只能引用只能引用左值,右值引用只能引用右值。
但是const & 可以引用右值

右值引用解决什么问题呢?

  1. 对于一个函数返回值不能用引用且拷贝开销很大的情况。比如to_string 的返回值 就是string 不能是 &string 因为 它的生命周期只在函数内部。str 出了to_string 就销毁了。

在这里插入图片描述

my::string s1 = my::to_string(123);
// 会经历 str 的构造,拷贝构造临时对象(深拷贝),赋值构造(深拷贝) s1 开销就很大

所以我们用移动构造优化它

移动构造

就是 参数是右值引用的构造。

string(string&& s)
	:_str(nullptr)
{
	cout << "string(string&& s) -- 移动构造" << endl;
	swap(s);
}

// 移动赋值
string& operator=(string&& s)
{
	cout << "string(string&& s) -- 移动赋值" << endl;
	swap(s);

	return *this;
}

在这里插入图片描述
大大节省了深拷贝的成本。
2.匿名对象直接当作函数的参数

string s1 = "hh";
vector<string> v;
v.push_back(s1);

//
v.push_back("hh");

上面的写法先构造s1,然后s1再拷贝构造给v中的data。
下面的写法是构造匿名对象,然后匿名对象直接移动构造给data,就不走深拷贝了。

值得注意的是右值引用本身的属性是左值的因为这样才能修改。左值有常属性。

万能引用

形式

template class<T &&>
void func(T && val)
{
	....	
}

与右值引用的区别就是上面带了个模板,我们传右值他就识别成右值,传左值它识别成左值

完美转发

格式

template class<T &&>
void func(T && val) //万能引用
{
	do_something(forword<T>(val)); // 完美转发
}

完美转发常常和完美应用一起使用的,主要是防止右值引用的属性是左值,传给下一层被认为是左值了,从而走不到移动构造,移动拷贝等。

lambada表达式

lambada表达式本质编译器帮我们生产了一个仿函数。

格式

[]()-> return {} // -> 和return 可省 但是这[] 捕获列表不能省 
//比如
[](int x, int y ) -> return (x+y;);

[=] 传值的方式捕获同一作用域的所有变量
[&]传引用的方式捕获同一作用域的所有变量
还可以混用比如[&,a,b]。 除了a,b 以外按转值捕获,其他按引用捕获。

可变参数模板

template class<...Args>
void func(Args ...args)
{

}

可变参数模板实现打印不同类型

// 编译时确定类型,所以要_cpp_print() 递归到最后,参数为空。
void _cpp_print() 
{

}
template<class T,class ... Args>
void _cpp_print(T & val, Args ...args)
{
	cout << val << " ";
	_cpp_print(args...);
}

template <class ...Args >
void cpp_print(Args... args)
{
	_cpp_print(args...);
}

在这里插入图片描述

template <class T>
int printArg(T &t)
{
	cout << t << " ";
	return 0;
}

template <class ...Args>
void cpp_print(Args...args)
{
	int arr[] = { printArg(args)... };
}

在这里插入图片描述

emplace_push

在这里插入图片描述
emplace_back 用的就是可变参数模板,在参数大于1的情况下,emplace_back 的效率比push_bakc更高。因为push_back 对于左值中间会走构造然后拷贝构造,对于右值会走构造,然后移动构造。
但是emplace_back 是直接传递的参数包,最后底层直接构造。

以list的emplace_back的实现举例

在这里插入图片描述

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值