• c++ std::reference_wrapper


    reference_wrapper

    reference_wrapper是一个模板类

    template <class T> class reference_wrapper;
    
    • 1

    用类型T实例化的reference_wrapper类能包装该类型的一个对象,并产生一个reference_wrapper< T >类型的对象,该对象就像是一个引用,与普通引用最大的不同是:该引用可以拷贝或赋值。

    特点:没有默认构造函数,可以用一个想要引用的对象构造,或者用另一个reference_wrapper对象构造

    int a = 10;
    int b = 100;
    reference_wrapper<int> r1 = a;
    reference_wrapper<int> r2 = r1;		拷贝构造
    r1 = 1;			错误,赋值运算符只接收同类型的对象
    r1 = b;		    正确,利用 b 构造一个临时对象,再用=运算符赋给 r1
    r1 = r2;			正确
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    get函数

    ref()返回的是一个reference_wrapper对象,并不是该对象的引用,所以如果要对返回对象调用成员函数就会报错。使用reference wrapper对象的get()方法,返回真正的引用(实际上reference wrapper是用指针表现出引用的所有特性,所以返回的应该是指针指向的对象)。

    通过get成员获取到reference_wrapper所引用的对象,从而进行修改其值等操作。访问所引用的对象的话,直接访问reference_wrapper对象即可

    int a = 10;
    reference_wrapper<int> r1 = a;
    cout << r1 << endl;	// 10
    cout << r1.get() << endl;	// 10
    r1.get() = 100;
    cout << r1.get() << endl;	// 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    特殊用法

    可以存入容器中
    普通的引用不是对象,所以无法存入任何标准库容器。reference_wrapper包装的引用就可以被存入容器中。

    可以像普通的引用一样作为实参传入函数
    一个reference_wrapper< T >类型的对象,可以作为实参,传入 形参类型为T的函数中

    void func1(int value) { value = 100; }		不过 value 只是个拷贝,不是引用
    void func2(int& value) { value = 1000; }	传入的是引用
    int a = 10;
    reference_wrapper<int> r = a;
    func1(r);		传入的是 r 引用的值的 拷贝
    cout << a << endl;	 10
    func2(r);		传入的是 r 引用的值的 引用
    cout << a << endl;	1000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    函数func的参数类型为int,而传递给func的参数确是reference_wrapper类型的对象。

    • 若reference_wrapper包裹的引用是可以调用的,则reference_wrapper对象也是可调用的
    • reference_wrapper 常通过引用传递对象给std::bind函数或者std::thread构造函数
    • std::ref 和std::cref 通常用来产生一个reference_wrapper对象,ref()就是用reference_wrapper来包裹对象的一个简化写法。
    auto r=ref(o);
    //等价于
    referencce_wrapper<dectype(o)> r(o);
    
    • 1
    • 2
    • 3

    示例

    #include 
    using namespace std;
    
    void func(int a, int b)
    {
        cout << "a = " << a <<",";
        cout << "b = " << b << endl;
    }
    
    void func1(int i)
    {
        cout << "i = " << i << endl;
    }
    
    int main()
    {
        // 包裹函数指针
        std::reference_wrapper<void(int,int)> f0 = func;
        f0(5,7); 		// a = 5,b = 7
    
        auto f1 = std::ref(func);
        f1(5,7);		// a = 5,b = 7
    
        // 和bind结合使用
        int i = 10;
    
        auto f2 = std::bind(func1, i);
        auto f3 = std::bind(func1, std::ref(i));
    
        i = 30;
    
        f2();	// i = 10
        f3();	// i = 30
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    CentOS 7 安装mariadb
    Mathematica对函数表达式求导并设置为新的自定义函数
    以太网 VLAN(简介、MAC地址表与VLAN)
    postman连接websocket, 建立连接、聊天测试(v8.5.1)
    whistle 的使用
    【网站架构】1小时1亿订单是否能扛住?压力、性能测试的步骤
    机器人地面站-[QGroundControl源码解析]-[2]
    【数据结构基础】之栈与队列介绍,生动形象,通俗易懂,算法入门必看
    SSH工具:XShell 常见的快捷命令整理汇总
    vue分片上传视频并转换为m3u8文件并播放
  • 原文地址:https://blog.csdn.net/weixin_44347020/article/details/133273979