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

  • 相关阅读:
    Navicat 15 最新破解版下载_永久激活注册码(附图文安装教程) Java大师
    idea30天免费试用,看看到底好不好用 Java大师
    TypeScript学习001
    [PE 741] Binary grid colouring
    ORACLE 查看被锁的表、导致锁表的目标机器、及对应锁表语句
    Hook Formulae and Schubert Calculus
    7个葫芦娃的养鸡日记系列1
    protobuf 'NoneType' object has no attribute 'message_types_by_name'
    windows bat 跳转到当前目录执行命令
    Android64位库编译遇到的问题和处理方法
  • 原文地址:https://www.cnblogs.com/diegodu/p/6868553.html
Copyright © 2020-2023  润新知