Boost学习之指针容器--pointer_container

有时,我们可能需要一个包含指针的容器.比如存放一些不可拷贝的对象或者想在容器里存放基类以实现多态.尽管我们可以直接定义存放指针的STL容器,不过这样并不方便,我们得处处小心,在清空或删除容器里的元素时我们要保证异常安全地回收指针所指向的对象,以防内存泄漏.

一个好的办法是使用共享智能指针的容器,如std::vector<boost::shared_ptr<T> >,不过这样做的话智能指针所带来的开销显然太大了.

Boost.pointer_container提供了和标准相似的容器,只是它维护的是指针所指的对象.

要使用Boost.pointer_container只需包含下面的头文件即可

#include <boost/ptr_container/ptr_container.hpp>

 

一个简单的例子


  1. #include <iostream>
  2. #include <boost/ptr_container/ptr_container.hpp>
  3.  
  4. using namespace std;
  5. using namespace boost;
  6.  
  7. struct base{  //基类
  8.     virtual void print()=0;
  9.         virtual ~base(){}
  10. };
  11.  
  12. struct A:base{ //A,从base继承
  13.     void print(){
  14.         cout << "A" << endl;
  15.     }
  16. };
  17.  
  18. struct B:base{ //B,从base继承
  19.     void print(){
  20.         cout << "Here is B" << endl;
  21.     }
  22. };
  23.  
  24. struct C:base{ //C,从base继承
  25.     C(string str)
  26.         :m_str(str){}
  27.     void print(){
  28.         cout << "C:" << m_str << endl;
  29.     }
  30. private:
  31.     string m_str;
  32. };
  33.  
  34. int main()
  35. {
  36.     ptr_vector<base> data;
  37.     data.push_back(new A);
  38.     data.push_back(new B);
  39.     data.push_back(new C("hello"));
  40.     data.push_back(new C("world"));
  41.    
  42.     for(ptr_vector<base>::iterator itr=data.begin(); itr!=data.end(); ++itr)
  43.     {
  44.         itr->print();
  45.     }
  46.  
  47.     return 0;
  48. }

运行结果:

A
Here is B
C:hello
C:world

应该注意到,这里没有内存泄漏,在ptr_vector<base>析构时会删除容器内指针所指向的对象.

本例中,我们使用了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,它不过是Boost.Array的简单包装罢了.

毫无悬念地,这些指针容器是STL兼容的,比如上面的循环打印用这句代替:

for_each(data.begin(), data.end(), mem_fun_ref(&base::print));

 

其它问题


空值

如果向容器中插入NULL, 默认情况是抛出一个异常. 如果想让指针容器能保存NULL指针,那么声明容器时就必须使用nullable来包装数据类型,例如:

boost::ptr_vector< boost::nullable<base> > animals_type;

克隆能力

默认情况下,容器或迭代器之间的赋值并不是简单的指针复制,而是使用拷贝构造函数产生一个新的拷贝.比如:

  1. struct C:base{
  2.     C(string str)
  3.         :m_str(str){
  4.         cout << "C:con " << this << ' ' << str <<endl;
  5.     }
  6.  
  7.     C(){
  8.         cout << "C:con " << this <<endl;
  9.     }
  10.  
  11.     C(const C& oth){
  12.         m_str = oth.m_str;
  13.         cout << "C:copy " << this << ' ' << m_str <<endl;
  14.     }
  15.  
  16.     ~C(){
  17.         cout << "C:decon " << this <<endl;
  18.     }
  19.     void print(){
  20.         cout << "C:" << m_str << endl;
  21.     }
  22. private:
  23.     string m_str;
  24. };
  25.  
  26. int main()
  27. {
  28.     ptr_vector<C> data;
  29.     data.push_back(new C("hello"));
  30.     data.push_back(new C("world"));
  31.    
  32.     ptr_vector<C> dataX = data;
  33.  
  34.     return 0;
  35. }

显示两次构造,两次拷贝,四次析构. 说明ptr_vector<C> dataX = data;使用了拷贝构造函数生成了自己的对象实例.

我们可以通过定义T* new_clone(const T&)来改变这种行为:

在上例的main()函数之前定义:

  1. C* new_clone(const C& orig)
  2. {
  3.     cout << "C:clone" << endl;
  4.     return new C("cloned");
  5. }

这次运行结果显示它调用了两次new_clone而不是拷贝了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

libzdb 连接到mysql_MySQL 连接

MySQL 连接使用mysql二进制方式连接您可以使用MySQL二进制方式进入到mysql命令提示符下来连接MySQL数据库。实例以下是从命令行中连接mysql服务器的简单实例&#xff1a;[roothost]# mysql -u root -pEnter password:******在登录成功后会出现 mysql> 命令提示窗口&#xff…

python ios 坐标点击_python点击鼠标获取坐标(Graphics)

使用Python进行图像编程&#xff0c;要使用到Graphics库。下面列举出较常用的代码from graphics import *#设置画布窗口名和尺寸win GraphWin(hehe, 666, 666)#关闭画布窗口win.getMouse()win.close()#画点pt Point(100, 100)pt.draw(win)#画圆cir Circle(Point(200, 200), …

C++ 11右值引用

C 11中引入的一个非常重要的概念就是右值引用。理解右值引用是学习“移动语义”&#xff08;move semantics&#xff09;的基础。而要理解右值引用&#xff0c;就必须先区分左值与右值。对左值和右值的一个最常见的误解是&#xff1a;等号左边的就是左值&#xff0c;等号右边的…

mysql dml ddl优先级_MYSQL入门操作和常规DML、DDL、DQL使用

刷新权限&#xff0c;将某些权限从硬盘刷新到内存中(修改root密码自带隐式刷新权限操作)mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)mysql>查看服务端口mysql> show variables like port;----------------------| Variable_name | Value |--------…

C语言中字符串如何转换为二进制、八进制、十进制、十六进制

在C语言某个程序当中需要把文本16进制转换成对应的16进制数&#xff0c;比如字符串"0x1a"转换成10进制的26&#xff0c;可以用以下函数来实现 相关函数: atof, atoi, atol, strtod, strtoul 表头文件: #include <stdlib.h> 定义函数: long int strtol(const…

python遍历循环中的遍历结构可以是什么_(一)Python入门-4控制语句:06for循环结构-遍历各种可迭代对象-range对象...

一&#xff1a;for循环和可迭代对象遍历for 循环通常用于可迭代对象的遍历。for 循环的语法格式如下&#xff1a;for 变量 in 可迭代对象&#xff1a;循环体语句可迭代对象&#xff1a;Python包含以下几种可迭代对象&#xff1a; 1. 序列。包含&#xff1a;字符串、列表、元组 …

C++11中的右值引用及move语义编程

C0x中加入了右值引用&#xff0c;和move函数。右值引用出现之前我们只能用const引用来关联临时对象&#xff08;右值&#xff09;&#xff08;造孽的VS可以用非const引用关联临时对象&#xff0c;请忽略VS&#xff09;&#xff0c;所以我们不能修临时对象的内容&#xff0c;右值…

IBatis 映射文件 sql 中大于、小于等符号转义

相信好多朋友在写配置文件的时候&#xff0c; 直接写 > 、<、>、< 编译不通过! 这些其实就是 xml 文体的特殊符号,在编写是需要转义&#xff0c;有两种方式处理&#xff0c;如下: 方法一 : 直接替换 <<>><><>&&amp;&apos…

python入侵数据库数据库_一个简单的Python访问Mysql数据库例子

2020/11/3操作记录搭建好Python的数据环境之后&#xff0c;接下来就是在Python代码中访问数据库我先在Navicat图形化界面创建一个数据库命名为pythontest&#xff0c;再在数据库中创建了一个表studentinfo有nid,nname,ngrade,nage四个字段&#xff0c;nid为主键递增。通过查询编…

r语言散点图_R语言 | 散点图入门:以声学元音图为例

R语言语言学与R语言的碰撞Xu & YangPhoneticSan学习参考Discovering Statistics Using RStatistics for Linguistics with RHow to Do Linguistics with RR in ActionAnalyzing Linguistic DataR Graphics Cookbook Recap可以使用plot( )函数进行基础的制图。调用ggplot2包…

oracle中如何创建dblink

当用户要跨本地数据库&#xff0c;访问另外一个数据库表中的数据时&#xff0c;本地数据库中必须创建了远程数据库的dblink,通过dblink本地数据库可以像访问本地数据库一样访问远程数据库表中的数据。下面讲介绍如何在本地数据库中创建dblink. 创建dblink一般有两种方式&#x…

哪里的mysql性能监控_mysql性能监控工具Innotop简介及配置

# wget http://innotop.googlecode.com/files/innotop-1.9.0.tar.gz# tar -zxvf innotop-1.9.0.tar.gz# cd innotop-1.9.0安装INNOTOP工具非常简单&#xff0c;其是由PERL写的&#xff0c;当然需要PERL环境和相关的工具包。在安装之前先要确定你的系统安装了Time::HiRes,Term::…

python能不能爬数据库_python爬取数据后不能写入到数据库中

目标&#xff1a;去爬当当网某页内容中的书籍的名称&#xff0c;链接和评论数&#xff0c;然后写入数据库中pipelins内容如下&#xff1a;import pymysqlclass DangdangPipeline(object):def process_item(self, item, spider):conn pymysql.connect(host"127.0.0.1"…

mysql创建表里主码和外码_SQL语言创建表时候怎么定义主码和外码

展开全部SQL语言创建表时候用Primary Key(属性名)定义主码&#xff0c;用Foreign Key(属性名)定义外码。主码是一种唯一关键字&#xff0c;表定62616964757a686964616fe59b9ee7ad9431333433623064义的一部分。一个表的主码可以由多个关键字共同组成&#xff0c;并且主码的列不能…

Autodesk 360 Mobile不能显示图片?

在6月21号的DevLab上&#xff0c;有一位朋友说Autodesk 360 Mobile在iPad上不能显示JPG图片预览。我当时没带iPad&#xff0c;不能测试。后天回家在Autodesk 360 Mobile 3.0试了一下&#xff0c;还真是这样。 这应该是Autodesk 360 Mobile 3.0的bug&#xff0c;不过升级到Autod…

关于std:auto_ptr

很多人听说过标准auto_ptr智能指针机制&#xff0c;但并不是每个人都天天使用它。这真是个遗憾&#xff0c;因为auto_ptr优雅地解决了C设计和编码中常见的问题&#xff0c;正确地使用它可以生成健壮的代码。本文阐述了如何正确运用auto_ptr来让你的代码更加安全——以及如何避免…

unity镜头边缘羽化_【后期修图】如何利用Ps中的自适应广角滤波器校正镜头失真?...

当用广角镜头拍摄对象时&#xff0c;透视问题通常以线条的形式出现&#xff0c;这应该是直的&#xff0c;但看起来是弯曲的和扭曲的。这通常被称为桶形失真&#xff0c;其主要发生在广角镜头中&#xff0c;因为图像的放大率越远&#xff0c;主体离镜头的光轴越远。简单来说&…

mysql查看事件任务内容_MySql事件计划任务

DROP EVENT IF EXISTS eve1;DELIMITER $$CREATE EVENT eve1 ON SCHEDULE EVERY 1 SECOND STARTS NOW() ENDS NOW()1ON COMPLETION PRESERVEDISABLEDOBEGINUPDATE testtable1 SET age age1 WHERE id 1;END$$DELIMITER ;SELECT * FROM testtable1;SELECT NOW();/*标准创建语句E…

Delphi 对象的创建(create)与释放(free/destory)

Delphi 对象的创建(create)与释放(free/destory) 1、Create参数为:nil/self/application的区别&#xff0c;最好能看到实际效果的区别 例如: My : TMy.Create(X); 其中的 X 将会成为控件 My 的 Owner 属性, 可能会不只一个控件把 X 当作 Owner. 当 X 释放时, 它会同时释放那些…

用引用返回值(转)

函数返回值时&#xff0c;要生成一个值的副本。而用引用返回值时&#xff0c;不生成值的副本。例如&#xff0c;下面的程序是有关引用返回的4种形式&#xff1a;//*********************//**   ch9_6.cpp  **//********************* #include <iostream.h> float tem…