boost--ref

一、ref简介html

  reference_wrapper包含在ref库中,它是引用包装器类型,即其内部包装了引用。python

  成员函数get()、get_pointer()分别能够得到被包装的引用和其指针。使用须要包含头文件"boost/ref.hpp"。c++

#include "boost/ref.hpp"
#include <cassert>
int main()
{
    int x = 5;
    boost::reference_wrapper<int> rw(x);

    rw.get() = 10; //得到引用
    *rw.get_pointer() = 15; //得到指针

    int n = rw; //隐式转换为int
    assert(x == rw); //隐式转换为int

    rw = 20; //错误!引用包装器不能做为左值
    (int&)rw = 20; //显示转换为int&,这样能够做为左值    
    assert(x == 20);

    boost::reference_wrapper<int> rw2(rw); //拷贝构造
    rw.get() = 25;
    assert(rw2.get() == 25);//rw2也是x的一个引用对象

    return 0;
}
View Code

  模板类is_reference_wrapper<T>用来判断类型T是不是一个reference_wrapper类型:经过其成员变量value。算法

  模板类unwrap_reference<T>用来得到类型T的真实类型:经过其内部类型定义type。c#

#include "boost/ref.hpp" #include <cassert>
int main() { int n = 10; boost::reference_wrapper<int> rw(n); assert(boost::is_reference_wrapper<decltype(rw)>::value); assert(!boost::is_reference_wrapper<decltype(n)>::value); string str; boost::reference_wrapper<string> rws(str); cout << typeid(boost::unwrap_reference<decltype(rws)>::type).name() << endl; return 0; }
View Code

  使用函数ref()和cref()能够很方便的构造reference_wrapper和const reference_wrapper对象,它们能够根据参数的类型推导出引用的类型。app

  除了成员函数get(),工具函数unwrap_ref()也能够得到引用包装器内包装的引用,并且其参数也能够不是引用包装器类型,这时候它直接返回参数的引用。ide

#include "boost/ref.hpp" #include <cassert>
int main() { int x = 5; auto rw = boost::ref(x); //使用ref()定义了一个reference_wrapper对象
 rw.get() = 10;//得到引用
    boost::unwrap_ref(rw) = 15; //得到引用
    assert(rw == 15); //隐式转换
    
    return 0; }
View Code

  能够把reference_wrapper类型对象直接赋值给对应类型的变量,reference_wrapper类型能够隐式转化为相对应类型:函数

int i = 10;
int n = ref(i); //隐式转换为int
View Code

  reference_wrapper类型对象不能直接做为左值当作被包装的引用来赋值使用,若是要对被包装的引用赋值的话有三种方法:工具

①、ref(x).get() = 10; //get()得到内部引用来做为左值
②、(int&)ref(x) = 10; //指定显示转换来做为左值
④、unwrap_ref(ref(x)) = 10; //unwrap_ref()得到内部引用来做为左值
View Code

二、ref做用1spa

  对于一个模板函数,函数调用时其具体类型能够为一个引用包装器类型,eg:

#include "boost/ref.hpp"
template<typename T>
void TestFun(T n)
{
    boost::unwrap_ref(n) = 10; //T类型多是引用包装reference_wrapper类型,因此应该使用unwrap_ref
}

int main()
{
    int num = 0;
    //TestFun(num); //输出为0
    TestFun(boost::ref(num)); //输出为10

    return 0;
}
View Code

  当调用TestFun()时传入的是变量num则TestFun()为值传递,输出为0,传入的是引用包装类型则TestFun()为引用传递,输出为10。

三、ref做用2

  STL中的算法大量使用了函数对象做为谓词参数,好比下面示例的for_each()算法:

#include <vector> #include <algorithm> #include "boost/assign.hpp"
using namespace boost::assign; class Square { public: void operator()(int& x) { x = x * x; } }; int main() { vector<int> v = list_of(1) (2) (3) (4); for_each(v.begin(), v.end(), Square()); auto iter = v.begin(), iterEnd = v.end(); for (; iter != iterEnd; iter++) cout << *iter << endl; return 0; }
View Code

  上面的for_each()中谓词对象参数就是拷贝传参,即值传递。有的时候函数对象的拷贝代价太高(内部状态复杂),或者咱们不但愿拷贝对象(防止内部状态改变),或者拷贝是禁止的(noncopyable、单件),这时候咱们能够传入函数对象的ref()引用包装器类型,eg:

#include <vector> #include <algorithm> #include <functional> #include "boost/assign.hpp"
using namespace boost::assign; class Square { public: void operator()(int& x) { x = x * x; } }; int main() { Square sq; vector<int> v = list_of(1) (2) (3) (4); for_each(v.begin(), v.end(), ref(sq)); auto iter = v.begin(), iterEnd = v.end(); for (; iter != iterEnd; iter++) cout << *iter << endl; return 0; }
View Code

  以上代码咱们直接使用了ref(),由于C++11中已经包含了ref库,使用时包含头文件<functional>便可。boost中的ref不支持对函数对象构造引用包装器类型,C++11中的ref没有这种限制。

四、ref做用3

  bind采用拷贝的方式存储绑定的参数,以下为使用count_if()算法来得到容器中元素长度小于5的元素个数,bind绑定len到仿函数的第二个参数,len参数是值传递,即便在operator()中被声明为了int&:

#include "boost/bind.hpp"
class CLenShorterThan
{
public:
    bool operator() (const string& str, int& len)
    {
        int iLen = len;
        len = 0;
        return str.length() < iLen;
    }
    typedef bool result_type;
};

int main()
{
    vector<string> myVector = list_of("c++") ("c#") ("python");
    int len = 5;
    int count = count_if(myVector.begin(), myVector.end(), bind(CLenShorterThan(), _1, len));
    cout << len << endl; //输出为5

    return 0;
}
View Code

  能够给bind绑定的参数传入ref()引用包装类型,使参数为引用传递:

#include "boost/bind.hpp"
class CLenShorterThan
{
public:
    bool operator() (const string& str, int& len)
    {
        int iLen = len;
        len = 0;
        return str.length() < iLen;
    }
    typedef bool result_type;
};

int main()
{
    vector<string> myVector = list_of("c++") ("c#") ("python");
    int len = 5;
    int count = count_if(myVector.begin(), myVector.end(), bind(CLenShorterThan(), _1, ref(len)));
    cout << len << endl; //输出为0

    return 0;
}
View Code

 五、ref做用4

 function使用拷贝语义来保存函数或函数对象,当函数或函数对象很复杂或者禁止拷贝的时候能够使用ref()以解决拷贝的代价和问题。具体示例可参见文章:boost--function中使用function对象存储函数对象用于回调的示例代码。

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息