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 ...
随机推荐
- 求高精度幂(poj1001)
Description Problems involving the computation of exact values of very large magnitude and precision ...
- 【BZOJ 4104】【THUSC 2015】解密运算
http://www.lydsy.com/JudgeOnline/problem.php?id=4104 网上题解满天飞,我也懒得写了 #include<cstdio> #include& ...
- 【数形结合】Erratic Expansion
[UVa12627]Erratic Expansion 算法入门经典第8章8-12(P245) 题目大意:起初有一个红球,每一次红球会分成三红一蓝,蓝球会分成四蓝(如图顺序),问K时的时候A~B行中有 ...
- HDU 6040 Hints of sd0061(nth_element)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6040 [题目大意] 给出一个随机数生成器,有m个询问,问第bi小的元素是啥 询问中对于bi< ...
- 【manacher】HDU3068-最长回文
[题目大意] 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. [manacher知识点] ①mx - i > P[j] 的时候,以S[j]为中心的回文子串 ...
- [BalkanOI2016]Lefkaritika
题目大意: 一个n*m的格子上有b个障碍物,现在让你往上面放正方形(长宽在格线上).问可以放多少种边长.位置不同的正方形? 思路: 很容易想到一个O(n^3)的暴力: 首先前缀和,然后枚举某一个顶点和 ...
- Problem D: 零起点学算法94——输出矩阵
#include<stdio.h> int main() { ][]; while(scanf("%d %d",&n,&m)!=EOF) { ; ;i& ...
- APK Develop——SMS Timer
SMS Timer APK 描述: 在设定时间后向设定手机号码发送设定的内容的短信. 权限获取: <manifest xmlns:android="http://schemas.and ...
- CentOS 6.9下配置安装KVM
注意:KVM一切安装和运行都是在root用户下完成的,并且只有root才能支持某些软件. 一.准备工作: 1.查看系统版本.内核版本 ##查看系统版本 # cat /etc/redhat-releas ...
- SpringMVC_入门项目
本项目是SpringMVC的入门项目,用于演示SpringMVC的项目配置.各层结构,功能较简单 一.Eclipse中创建maven项目 二.pom.xml添加依赖 1 2 3 4 5 6 7 8 9 ...