boost--ref
1、ref简介
reference_wrapper包含在ref库中,它是引用包装器类型,即其内部包装了引用。
成员函数get()、get_pointer()分别可以获得被包装的引用和其指针。使用需要包含头文件"boost/ref.hpp"。
#include "boost/ref.hpp"
#include <cassert>
int main()
{
int x = ;
boost::reference_wrapper<int> rw(x); rw.get() = ; //获得引用
*rw.get_pointer() = ; //获得指针 int n = rw; //隐式转换为int
assert(x == rw); //隐式转换为int rw = ; //错误!引用包装器不能作为左值
(int&)rw = ; //显示转换为int&,这样可以作为左值
assert(x == ); boost::reference_wrapper<int> rw2(rw); //拷贝构造
rw.get() = ;
assert(rw2.get() == );//rw2也是x的一个引用对象 return ;
}
模板类is_reference_wrapper<T>用来判断类型T是否是一个reference_wrapper类型:通过其成员变量value。
模板类unwrap_reference<T>用来获得类型T的真实类型:通过其内部类型定义type。
#include "boost/ref.hpp"
#include <cassert>
int main()
{
int n = ;
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 ;
}
使用函数ref()和cref()可以很方便的构造reference_wrapper和const reference_wrapper对象,它们可以根据参数的类型推导出引用的类型。
除了成员函数get(),工具函数unwrap_ref()也可以获得引用包装器内包装的引用,而且其参数也可以不是引用包装器类型,这时候它直接返回参数的引用。
#include "boost/ref.hpp"
#include <cassert>
int main()
{
int x = ;
auto rw = boost::ref(x); //使用ref()定义了一个reference_wrapper对象 rw.get() = ;//获得引用
boost::unwrap_ref(rw) = ; //获得引用
assert(rw == ); //隐式转换 return ;
}
可以把reference_wrapper类型对象直接赋值给对应类型的变量,reference_wrapper类型可以隐式转化为相对应类型:
int i = ;
int n = ref(i); //隐式转换为int
reference_wrapper类型对象不能直接作为左值当做被包装的引用来赋值使用,如果要对被包装的引用赋值的话有三种方法:
①、ref(x).get() = ; //get()获得内部引用来作为左值
②、(int&)ref(x) = ; //指定显示转换来作为左值
④、unwrap_ref(ref(x)) = ; //unwrap_ref()获得内部引用来作为左值
2、ref作用1
对于一个模板函数,函数调用时其具体类型可以为一个引用包装器类型,eg:
#include "boost/ref.hpp"
template<typename T>
void TestFun(T n)
{
boost::unwrap_ref(n) = ; //T类型可能是引用包装reference_wrapper类型,所以应该使用unwrap_ref
} int main()
{
int num = ;
//TestFun(num); //输出为0
TestFun(boost::ref(num)); //输出为10 return ;
}
当调用TestFun()时传入的是变量num则TestFun()为值传递,输出为0,传入的是引用包装类型则TestFun()为引用传递,输出为10。
3、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() () () ();
for_each(v.begin(), v.end(), Square()); auto iter = v.begin(), iterEnd = v.end();
for (; iter != iterEnd; iter++)
cout << *iter << endl; return ;
}
上面的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() () () ();
for_each(v.begin(), v.end(), ref(sq)); auto iter = v.begin(), iterEnd = v.end();
for (; iter != iterEnd; iter++)
cout << *iter << endl; return ;
}
以上代码我们直接使用了ref(),因为C++11中已经包含了ref库,使用时包含头文件<functional>即可。boost中的ref不支持对函数对象构造引用包装器类型,C++11中的ref没有这种限制。
4、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 = ;
return str.length() < iLen;
}
typedef bool result_type;
}; int main()
{
vector<string> myVector = list_of("c++") ("c#") ("python");
int len = ;
int count = count_if(myVector.begin(), myVector.end(), bind(CLenShorterThan(), _1, len));
cout << len << endl; //输出为5 return ;
}
可以给bind绑定的参数传入ref()引用包装类型,使参数为引用传递:
#include "boost/bind.hpp"
class CLenShorterThan
{
public:
bool operator() (const string& str, int& len)
{
int iLen = len;
len = ;
return str.length() < iLen;
}
typedef bool result_type;
}; int main()
{
vector<string> myVector = list_of("c++") ("c#") ("python");
int len = ;
int count = count_if(myVector.begin(), myVector.end(), bind(CLenShorterThan(), _1, ref(len)));
cout << len << endl; //输出为0 return ;
}
5、ref作用4
function使用拷贝语义来保存函数或函数对象,当函数或函数对象很复杂或者禁止拷贝的时候可以使用ref()以解决拷贝的代价和问题。具体示例可参见文章:boost--function中使用function对象存储函数对象用于回调的示例代码。
boost--ref的更多相关文章
- boost function bind ref
boost::function to encapsulate function pointers. 1. function #include <boost/function.hpp> #i ...
- 1,Boost -> Bind
#include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <iostream> usin ...
- boost和std中的thread的引用参数
boost 1.60.0 先上代码: #include <boost/thread.hpp> #include <iostream> void add(int &i) ...
- boost asio tcp server 拆分
从官方给出的示例中对于 boost::asio::ip::tcp::acceptor 类的使用,是直接使用构造函数进行构造对象,这一种方法用来学习是一个不错的方式. 但是要用它来做项目却是不能够满足我 ...
- Boost C++: 数据结构---tuple
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple_io.hpp> #include <boost/ ...
- boost.ASIO-可能是下一代C++标准的网络库
曾几何时,Boost中有一个Socket库,但后来没有了下文,C++社区一直在翘首盼望一个标准网络库的出现,网络上开源的网络库也有不少,例如Apache Portable Runtime就是比较著名的 ...
- boost------function的使用(Boost程序库完全开发指南)读书笔记
function是一个函数对象的“容器”,概念上像是c/c++中函数指针类型的泛化,是一种“智能函数指针”.它以对象的形式封装了原始的函数指针或函数对象,能够容纳任意符合函数签名的可调用对象. 因此, ...
- boost::function实践——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
代码段1: #include <boost/function.hpp> #include <iostream> float mul_ints(int x, int y) { r ...
- boost::bind实践2——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
直接代码: 代码段1: #include <iostream> #include <string> #include <boost/bind/bind.hpp> c ...
- boost::bind实践
第一部分源码为基础实践: /*Beyond the C++ Standard Library ( An Introduction to Boost )[CN].chm*/ /*bind的用法*/ #i ...
随机推荐
- TZOJ 1321 Girls and Boys(匈牙利最大独立集)
描述 the second year of the university somebody started a study on the romantic relations between the ...
- Jedis cluster命令执行流程剖析
Jedis cluster命令执行流程剖析 在Redis Cluster集群模式下,由于key分布在各个节点上,会造成无法直接实现mget.sInter等功能.因此,无论我们使用什么客户端来操作Red ...
- shelve
shelve是对pickle的封装 json & pickle是把所有的数据全部封装,一次性写入文件,而shelve可以把数据分类,以键值对的形式分别写入文件 shelve模块是一个简单的k, ...
- sourceTree git的一些命令
经常使用的三个命令 1.添加修改过的文件到缓冲区 git add. 2.commit到本地 git commit -am ' 更改描述' 3.如果是多人开发的话,中间可能会有别人先提交的这是就需要先把 ...
- jquery.form.js 使用以及问题(表单异步提交)
标注:我引用的js后报错 原因:是引用的js有冲突 我引用了两便jQuery: 转载:https://blog.csdn.net/cplvfx/article/details/80455485 使用方 ...
- c# 线程启动while(true) 死循环,里边的return导致线程退出情况,查错
写了一个线程 线程下启动了一个循环 while(true) { 里边有个判断 如果为空不操作, 有余这个线程是后加的,老程序里边因为有个return没关注,导致线程退出而不能不听的监控 } 线程启动一 ...
- js 逻辑运算符
两个逻辑运算符的操作顺序在自己的脑海里一直理不清,用js做了个实验 <script type="text/javascript"> if(false && ...
- 网站文章分享到微博,微信、qq空间--举例用织梦
有对应接口的,传递参数过去就行了,注意下面的{..},需要替换为你的内容,看参数名称你应该知道是什么东东 新浪地址接口http://service.weibo.com/share/share.php? ...
- iserver-数据库型数据源导入后原dataset名称和数据库表名不一致的问题
一.发现问题 系统中发现某个房屋的分层平面图查询不到 1.去sqlserver空间库中查询发现这个表‘房间_100200T001D001’不存在 2.在工作空间中查询发现是有这个数据集的 二.解决问题 ...
- PAT 1071 小赌怡情(15)(代码)
1071 小赌怡情(15 分) 常言道"小赌怡情".这是一个很简单的小游戏:首先由计算机给出第一个整数:然后玩家下注赌第二个整数将会比第一个数大还是小:玩家下注 t 个筹码后,计算 ...