C++11: reference_wrapper
https://oopscenities.net/2012/08/09/reference_wrapper/
Look at this piece of code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include <iostream> #include <functional> using namespace std; using namespace std::placeholders; void add( int a, int b, int & r) { r = a + b; } int main() { int result = 0; auto f = bind(add, _1, 20, result); f(80); cout << result << endl; return 0; } |
This program supposedly adds 80 to 20 and prints the result; it compiles perfectly but when you execute it; you get…. 0!
Why?
Because the bind
method receives its parameters as parameters-by-value and the “result” variable is copied before being passed to the bound function add
. Why?
Because bind
does not know if the parameters will still be valid when the actual invocation will be performed (remember, you could pass a function
object to other function passing local variables as arguments and invoking it from there).
The solution? Pretty simple:
1
2
3
4
5
6
7
8
9
10
11
|
int main() { int result = 0; auto f = bind(add, _1, 20, ref (result)); f(80); cout << result << endl; return 0; } |
I added the function ref
that sends our parameter as a reference to the bound function.
What does this function ref
do?
It is a template function that returns a reference_wrapper
object. A reference_wrapper
is a class template that wraps a reference in a concrete object.
Actually you could do something like:
1
2
3
4
5
6
7
8
9
10
11
12
|
int main() { int result = 0; reference_wrapper< int > result_ref(result); auto f = bind(add, _1, 20, result_ref); f(80); cout << result << endl; return 0; } |
and everything would continue working as expected.
As you can see, you can pass the reference_wrapper
by value and everything will work because its copy constructor copies the reference (actually, the reference_wrapper
implementations do not store a reference but a pointer to the data being referenced, but their methods expose it as a reference).
Other nice usage of this would be in cases where you need to have a container of references (the actual objects are stored in other container or in other place and you do not need/want to have copies or pointers to them). For example, you have these classes:
1
2
|
class A { }; class B : public A { }; |
And you want to have at the same time local variables pointing to them and you want them stored in a container:
1
2
3
4
5
6
7
|
int main() { A a, c; B b, d; vector<A> v = { a, b, c, d }; } |
Good? No! Bad at all! You are storing instances of class A in your vector. All the instances of B will be copied as instances of A (losing their specific attributes and all the polymorphic behavior and so on).
One solution? Storing pointers:
1
2
3
4
5
6
7
|
int main() { A a, c; B b, d; vector<A*> v = { &a, &b, &c, &d }; } |
It works, but it is not evident for the user of the container if s/he will be in charge of freeing the objects or not.
Other solution? Using references:
1
2
3
4
5
6
7
|
int main() { A a, c; B b, d; vector<A&> v = { a, b, c, d }; } |
Looks nice, but it does not compile; because you cannot specify reference types in a vector.
Real solution: Using reference_wrappers:
1
2
3
4
5
6
7
|
int main() { A a, c; B b, d; vector<reference_wrapper<A>> v = { a, b, c, d }; } |
Someone could argue: In which scenario is this thing useful?
If you create a UI frame using Java Swing, you probably create a subclass of the JFrame class, will specify your visual components as member variables and you will also add them into the JFrame’s component list. Implementing something similar in C++ using reference_wrappers would be quite elegant.
C++11: reference_wrapper的更多相关文章
- 地区sql
/*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...
- C++11的一些新特性
3.1.9崭新的Template特性 Variadic Template 可变参数模板 void print() { } template <typename T, typename… Type ...
- C++11包装引用
[C++11包装引用] 我们可以通过实体化样板类 reference_wrapper 得到一个包装引用 (wrapper reference).包装引用类似于一般的引用.对于任意对象,我们可以通过模板 ...
- c++11 : range-based for loop
0. 形式 for ( declaration : expression ) statement 0.1 根据标准将会扩展成这样的形式: 1 { 2 auto&& __ra ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- C++11新特性之八——函数对象function
详细请看<C++ Primer plus>(第六版中文版) http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html ...
- 引用传参与reference_wrapper
本文是<functional>系列的第3篇. 引用传参 我有一个函数: void modify(int& i) { ++i; } 因为参数类型是int&,所以函数能够修改传 ...
- C++11<functional>深度剖析
自C++11以来,C++标准每3年修订一次.C++14/17都可以说是更完整的C++11:即将到来的C++20也已经特性完整了. C++11已经有好几年了,它的年龄比我接触C++的时间要长10倍不止吧 ...
- WinForm 天猫2013双11自动抢红包【源码下载】
1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...
随机推荐
- 四川oi 萌萌哒 (分层并查集)
萌萌哒 时间限制: 1 Sec 内存限制: 256 MB提交: 12 解决: 2[提交][状态][讨论版] 题目描述 一个长度为 n 的大数,用 S1S2S3...Sn表示,其中 Si表示数的第 ...
- Codeforces Round #119 (Div. 2) Cut Ribbon(DP)
Cut Ribbon time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- Sqli-labs less 12
Less-12 本关和less11是类似的,只是在id 的参数的处理上有一定的不同 当输入username:admin" Password: (随便) 报错后的结果为: You have a ...
- BZOJ 1106 [POI2007]立方体大作战tet(树状数组)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1106 [题目大意] 给定玩家一个有2n个元素的栈,元素一个叠一个地放置. 这些元素拥有 ...
- 【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容
[题目大意] 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费 ...
- 【深度优先搜索】mr353-取奶
应该是USACO的题目,暂时没有找到对应出处. [题目大意] 农夫约翰要量取 Q(1 <= Q <= 20,000)夸脱(夸脱,quarts,容积单位——译者注) 他的最好的牛奶,并把它装 ...
- 解决maven无法下载jar的问题
先去本地仓库查看是否有没有jar包,如果没有并且存在除jar包以外的文件,先将文件删除,重新用maven下载一遍.如果还是不行,就自己下载jar包导入到本地仓库,但是不能手动的添加文件夹和pom.xm ...
- Codeforces Round #341 (Div. 2) D. Rat Kwesh and Cheese 数学
D. Rat Kwesh and Cheese 题目连接: http://www.codeforces.com/contest/621/problem/D Description Wet Shark ...
- Educational Codeforces Round 7 F. The Sum of the k-th Powers 拉格朗日插值法
F. The Sum of the k-th Powers 题目连接: http://www.codeforces.com/contest/622/problem/F Description Ther ...
- python 数据分析 Matplotlib常用图表
Matplotlib绘图一般用于数据可视化 常用的图表有: 折线图 散点图/气泡图 条形图/柱状图 饼图 直方图 箱线图 热力图 需要学习的不只是如何绘图,更要知道什么样的数据用什么图表展示效果最好 ...