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對象存儲函數對象用於回調的示例代碼。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息