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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值