首页 技术 正文
技术 2022年11月10日
0 收藏 619 点赞 4,011 浏览 3032 个字

C++11: reference_wrapper

Look at this piece of code:

12345678910111213141516171819202122 #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:

1234567891011 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:

123456789101112 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:

12 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:

1234567 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:

1234567 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:

1234567 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:

1234567 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.

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,494
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,495
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,133
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,297