Boost学习之指针容器--pointer_container
Boost.pointer_container提供了和标准相似的容器,只是它存放的是指针,维护的是堆分配的对象.
有时,我们可能需要一个包含指针的容器.比如存放一些不可拷贝的对象或者想在容器里存放基类以实现多态.尽管我们可以直接定义存放指针的STL容器,不过这样并不方便,我们得处处小心,在清空或删除容器里的元素时我们要保证异常安全地回收指针所指向的对象,以防内存泄漏.
一个好的办法是使用共享智能指针的容器,如std::vector >,不过这样做的话智能指针所带来的开销显然太大了.
Boost.pointer_container提供了和标准相似的容器,只是它维护的是指针所指的对象.
要使用Boost.pointer_container只需包含下面的头文件即可
#include
一个简单的例子
-
#include
-
#include
-
-
using namespace std;
-
using namespace boost;
-
-
struct base{ //基类
-
virtual void print()=0;
-
virtual ~base(){}
-
};
-
-
struct A:base{ //A,从base继承
-
void print(){
-
cout << "A" << endl;
-
}
-
};
-
-
struct B:base{ //B,从base继承
-
void print(){
-
cout << "Here is B" << endl;
-
}
-
};
-
-
struct C:base{ //C,从base继承
-
C(string str)
-
:m_str(str){}
-
void print(){
-
cout << "C:" << m_str << endl;
-
}
-
private:
-
string m_str;
-
};
-
-
int main()
-
{
-
ptr_vector data;
-
data.push_back(new A);
-
data.push_back(new B);
-
data.push_back(new C("hello"));
-
data.push_back(new C("world"));
-
-
for(ptr_vector::iterator itr=data.begin(); itr!=data.end(); ++itr)
-
{
-
itr->print();
-
}
-
-
return 0;
-
}
运行结果:
A Here is B C:hello C:world
应该注意到,这里没有内存泄漏,在ptr_vector析构时会删除容器内指针所指向的对象.
本例中,我们使用了ptr_vector,在Boost.pointer_container库中包含的指针容器有:
ptr_vector
ptr_list
ptr_deque
ptr_array
ptr_set
ptr_multi_set
ptr_map
ptr_multimap
除ptr_array以外,其它所有的容器都能与STL一一对应起来,除了以指针方式存入以外,使用方法没什么区别.至于ptr_array,它不过是的简单包装罢了.
毫无悬念地,这些指针容器是STL兼容的,比如上面的循环打印用这句代替:
for_each(data.begin(), data.end(), mem_fun_ref(&base::print));
其它问题
空值
如果向容器中插入NULL, 默认情况是抛出一个异常. 如果想让指针容器能保存NULL指针,那么声明容器时就必须使用nullable来包装数据类型,例如:
boost::ptr_vector< boost::nullable > animals_type;
克隆能力
默认情况下,容器或迭代器之间的赋值并不是简单的指针复制,而是使用拷贝构造函数产生一个新的拷贝.比如:
-
struct C:base{
-
C(string str)
-
:m_str(str){
-
cout << "C:con " << this << ' ' << str <
-
}
-
-
C(){
-
cout << "C:con " << this <
-
}
-
-
C(const C& oth){
-
m_str = oth.m_str;
-
cout << "C:copy " << this << ' ' << m_str <
-
}
-
-
~C(){
-
cout << "C:decon " << this <
-
}
-
void print(){
-
cout << "C:" << m_str << endl;
-
}
-
private:
-
string m_str;
-
};
-
-
int main()
-
{
-
ptr_vector data;
-
data.push_back(new C("hello"));
-
data.push_back(new C("world"));
-
-
ptr_vector dataX = data;
-
-
return 0;
-
}
显示两次构造,两次拷贝,四次析构. 说明ptr_vector dataX = data;使用了拷贝构造函数生成了自己的对象实例.
我们可以通过定义T* new_clone(const T&)来改变这种行为:
在上例的main()函数之前定义:
-
C* new_clone(const C& orig)
-
{
-
cout << "C:clone" << endl;
-
return new C("cloned");
-
}
这次运行结果显示它调用了两次new_clone而不是拷贝了.
Boost.pointer_container提供了和标准相似的容器,只是它存放的是指针,维护的是堆分配的对象.
新的成员函数
release:
声明:
auto_type release(iterator where)
作用:
把指针从容器中删除,并返回这个指针. auto_type是数据的智能指针,类似于std::auto_ptr.
transfer
声明:
template< class PtrSeqAdapter > void transfer( iterator before, PtrSeqAdapter::iterator first, PtrSeqAdapter::iterator last, PtrSeqAdapter& from ) // strong template< class PtrSeqAdapter > void transfer( iterator before, PtrSeqAdapter::iterator object, PtrSeqAdapter& from ) // strong
作用:
从另一容器from中转移指定的元素到本容器中.
replace
声明:
auto_type replace( iterator where, Ty_* x )
作用
用x替换where处的元素,返回被替换掉的元素.
类STL算法
因为存入指针容器的是指针,并且由容器负责所指对象的生命周期. 面迭代器表现的却是对象的引用,这种不一致造成了它不适合使用STL里那些会改变容器内容的算法(比如sort),所以指针容器自己提供了一些有用的算法:
排序
-
void sort( iterator first, iterator last )
-
void sort()
-
template< class Compare >
-
void sort( iterator first, iterator last, Compare comp )
-
template< class Compare >
-
void sort( Compare comp )
唯一
-
void unique( iterator first, iterator last )
-
void unique()
-
template< class Compare >
-
void unique( iterator first, iterator last, Compare comp )
-
template< class Compare >
-
void unique( Compare comp )
条件删除
-
template< class Pred >
-
void erase_if( iterator first, iterator last, Pred pred )
-
template< class Pred >
-
void erase_if( Pred pred )
归并
-
void merge( iterator first, iterator last,
-
ptr_sequence_adapter& from )
-
template< class BinPred >
-
void merge( iterator first, iterator last,
-
ptr_sequence_adapter& from, BinPred pred )
-
void merge( ptr_sequence_adapter& r )
-
template< class BinPred >
-
void merge( ptr_sequence_adapter& r, BinPred pred )
阅读(1765) | 评论(0) | 转发(0) |