场景:

  1. 在 remove_reference 结构体中能看到右值引用的身影 &&, 那么这里的右值引用究竟有什么用呢?

  2. 常常也发现int& 和int&& 这两种相似的应用类型,第一种是左值引用声明,另外一种是右值引用声明.
  3. 下面的样例直接參考的 cppreference,已经写的非常完整了,不是必需又一次写.

參考:

1.Reference declaration

2.Rvalue Reference Declarator: &&

3.Lvalue Reference Declarator: &

语法

左值引用声明: & attr(optional) declarator (1)

右值引用声明: && attr(optional) declarator (2) (since C++11)

左值引用声明 &

–1. 左值引用能够理解为对象的别名, 左值引用必须被初始化并且不能被又一次赋值.

#include <iostream>
#include <string> int main()
{
std::string s = "Ex";
std::string& r1 = s;
const std::string& r2 = s; r1 += "ample"; // modifies s
// r2 += "!"; // error: cannot modify through reference to const
std::cout << r2 << '\n'; // prints s, which now holds "Example"
}

–2. 在调用函数时,能够被用来作为引用參数.

#include <iostream>
#include <string> void double_string(std::string& s)
{
s += s; // 's' is the same object as main()'s 'str'
} int main()
{
std::string str = "Test";
double_string(str);
std::cout << str << '\n';
}

–3. 当一个函数的返回值是左值时, 这个函数的调用的表达式能够被觉得是一个左值表达式.


#include <iostream>
#include <string> char& char_number(std::string& s, std::size_t n)
{
return s.at(n); // string::at() returns a reference to char
} int main()
{
std::string str = "Test";
char_number(str, 1) = 'a'; // the function call is lvalue, can be assigned to
std::cout << str << '\n';
}

右值引用声明 &&

–1. 右值引用声明能够差别一个左值和右值.

–2. 右值引用直至Move语义的实现, 它能够把暂时对象(一般不能引用)的资源移动到其它地方去.

–3. 右值引用也能够用来扩展暂时对象的生命周期,

#include <iostream>
#include <string> int main()
{
std::string s1 = "Test";
// std::string&& r1 = s1; // error: can't bind to lvalue const std::string& r2 = s1 + s1; // okay: lvalue reference to const extends lifetime
// r2 += "Test"; // error: can't modify through reference to const std::string&& r3 = s1 + s1; // okay: rvalue reference extends lifetime
r3 += "Test"; // okay: can modify through reference to non-const
std::cout << r3 << '\n';
}

–4. 假设函数有左值和右值引用的重载,调用时会匹配调用, 传左值调用左值重载, 右值调用右值重载. 这样就能够支持Move Constructor 和 Move Assignment 的实现.

#include <iostream>
#include <utility> void f(int& x)
{
std::cout << "lvalue reference overload f(" << x << ")\n";
} void f(const int& x)
{
std::cout << "lvalue reference to const overload f(" << x << ")\n";
} void f(int&& x)
{
std::cout << "rvalue reference overload f(" << x << ")\n";
} int main()
{
int i = 1;
const int ci = 2;
f(i); // calls f(int&)
f(ci); // calls f(const int&)
f(3); // calls f(int&&)
// would call f(const int&) if f(int&&) overload wasn't provided
f(std::move(i)); // calls f(int&&)
}

最新文章

  1. Windows 10 下mysql 安装后无法启动问题
  2. 在asp.net WebForms中使用路由Route
  3. 今天遇到了批量删除 redis 某个前缀的所有 key,发现只能是这么解决。
  4. Intellij IDEA使用总结
  5. 点击 Run 之后发生了什么?
  6. linux驱动初探之杂项设备(控制两个GPIO口)
  7. left join与on,where 结合一起用的异同
  8. 【算法】A*改进算法
  9. centos下安装mysql步骤
  10. C语言的本质(8)——副作用与顺序点
  11. Sonar入门学习
  12. java jdk缓存-128~127的Long与Integer
  13. Html5 Canvas笔记(1)-CanvasAppTemplate代码
  14. lock了mutex的线程退出了却没有unlock时会怎么样?
  15. for循环输出树木的形状【java】
  16. java I/O工作机制
  17. C# Winform ListView控件
  18. [leetcode]152. Maximum Product Subarray最大乘积子数组
  19. eclipse老运行上一个程序之原因总结
  20. django直接操作MySQL,中文乱码

热门文章

  1. body标签相关
  2. 淘宝的TProfile分析
  3. maven项目打包jar,含有依赖jar
  4. cf- 297 &lt; b &gt; -- 区间翻转操作的优化
  5. BZOJ-2049 [SDOI2008]洞穴勘测
  6. DB2 Catalog浅析&amp;学习笔记
  7. [POJ2417]Discrete Logging(指数级同余方程)
  8. float浮动的学习
  9. python 序列化之pickle模块 json模块
  10. hdu 1250 树形DP