c++ 的 STL 中主要有 vector , list, map, set  , multimap,multiset

这些容器完全支持使用内置类型和指针(指针注意内存泄露问题)。

就是说乱用智能指针或其他指针作为容器元素,有可能2个元素指向同一个对象,2个元素(指针)对应一个对象,甚至更多

C++ 容器要求元素具有 object type,引用不是 object type。

#include <vector>
#include <boost/shared_ptr.hpp> using namespace std; class test {};
typedef boost::shared_ptr<test> test_ptr; int main()
{
vector<test> tmp;
vector<test*> tmp1;    //小心内存泄露,重复析构等问题
//vector<test&> tmp;    //直接编译通不过
vector<test_ptr> tmp2;
//vector<test_ptr&> tmp3;  //即使是boost的智能指针的引用也不行 return 0;
}

这些容器都要求元素类型满足以下2种情况:

(1)能被复制:向这些容器添加新元素时,容器会复制一份自己的版本,这要求容器使用的元素类型可以被复制,类类型需要复制构造函数的支持了

(2)能被赋值:在使用容器的删除、查找、访问、使用迭代器修改元素等许多情况下,都需要元素的赋值操作支持,类类型需要赋值操作符运算的支持

vector、list 中的单参数的resize 操作需要默认初始化指定个数的元素,类类型需要无参数的默认构造函数支持初始化

set、multiset, map和multimap中的键类型、  list 中的sort 操作 都需要 < 比较操作来排序,类类型需要 < 操作符运算的支持

在STL中,容器的元素要满足三个基本要求:可拷贝(copyable)、可赋值(assignable)、可析构(destroyable)。基本数据类型和自定义的类都满足这些条件,但是引用不满足,因为引用不能析构。

======================================================

http://wenku.baidu.com/view/8d049f4f767f5acfa1c7cd11.html

【摘要】对C++语言本身来说,它并不在乎用户把什么类型的对象作为STL容器的元素,因为模板类型参数在理论上可以为任何类型。比如说STL容器仅支持“值”语义而不支持“引用(&)”语义,并非因为模板类型参数不能为引用,而是因为如果容器元素为引用类型,就会出现“引用的引用”、“引用的指针”等C++语言不支持的语法和语义。智能指针是一种模拟原始指针行为的对象,因此理论上也可以作为容器的元素,就象原始指针可以作为容器元素一样。但是智能指针毕竟是一种特殊的对象,它们在原始指针共享实值对象的基础能力上增加了自动销毁实值对象的能力,如果将它作为容器的元素,可能导致容器之间共享元素对象实值,这不仅不符合STL容器的概念和“值”语义,也会存在安全隐患,同时也会存在许多应用上的限制,特别是象STL中的auto_ptr这样的智能指针。

可以作为STL容器的元素的数据类型一般来说需要满足下列条件: 
(1)可默认构造的(Default Constructible),也即具有public的default constructor,不论是用户显式定义的还是编译器自动合成的。但是用户定义的带参数的constructor(包括copy constructor)会抑制编译器合成default constructor。实际上并非任何情况下任何一种容器都强制要求其元素类型满足这一要求,特别是关联式容器,因为只有序列式容器的某些成员函数才可能明确地或隐含地使用元素类型的默认构造函数,如果你不使用这样的成员函数,编译器就不需要元素类型的默认构造函数; 
(2)可拷贝构造(Copy Constructible)和拷贝赋值(Copy Assignable)的,即具有public的copy constructor和copy assignment operator,不论是编译器自动合成的还是用户显式定义的。其它版本的operator=()重载并不会抑制编译器合成copy assignment operator,如果你没有显式定义它的话。这个条件可归结为:元素必须是可拷贝的(Copyable),但实际上拷贝赋值的要求也不是强制的,原因和默认构造函数类似;

(3)具有public的destructor,不论是编译器自动合成的还是用户显式定义的; (4)对于关联式容器,要求其元素必须是可比的(Comparable)。 
std::auto_ptr满足上述条件吗?至少满足前三条,因此至少可以作为序列式容器的元素;如果为auto_ptr定义了比较运算符的话,应该还可以把它作为关联式容器的元素。 
但是auto_ptr的特点是接管和转移拥有权,而不是像原始指针那样可以共享实值对象,

int tmp = 10;

int* p1 = &tmp;

int* p2 = &tmp;

指针p1 p2共享实值对象tmp;

即:auto_ptr在初始化时接管实值对象和拥有权,而在拷贝时(拷贝构造和拷贝赋值)会交出实值对象及其拥有权。因此,auto_ptr对象和它的拷贝绝对不会共享实值对象,任何两个auto_ptr也不应该共享同一个实值对象。这就是说,auto_ptr对象和它的拷贝并不相同。然而根据STL容器“值” 语义的要求,可拷贝构造意味着一个对象必须和它的拷贝相同(标准中的正式定义比这稍复杂一些)。同样,可赋值意味着把一个对象赋值给另一个同类型对象将产生两个相同的对象。显然,auto_ptr不能满足这一要求,似乎与上面的结论矛盾!

STL容器管理元素的方法是动态创建元素的拷贝

应该说,从应用的方便性和安全角度出发,容器应该要求其元素对象的拷贝与原对象相同或者等价,但auto_ptr显然不满足这一条。

======================================================

http://bbs.csdn.net/topics/310036165

容器元素比如vector对元素对象的唯一要求是可以复制构造。
但比如说你把auto_ptr对象用作了容器元素,虽然其也可以复制构造,只不过复制构造会破坏原始对象,你用了之后会导致未定义现象。

容器的大小是可以改变的,而且往往会自动改变。
对于vector来说,如果空间不够了,会自动增长,但是如果原来所在的空间不够的话,系统就会在另外一个地方分配一个满足需要的空间。
所以在此时,对于vector已有的元素也进行了移动,此时就会执行新的构造函数,同样还会把原来位置的旧元素析构掉。

如果同时存在两个vector,其中一个对旧元素执行了析构,会导致另外一个对同一个元素析构,这样就会出问题。

对于你举的例子没有这样的问题,这是因为对于char*执行的值拷贝。

所谓的“值语义”就是说可不可以拷贝的问题。std::auto_ptr不满足这个条件。

"值"的语义就是  每个元素都应该是单独的完整的元素,而其元素指针共享同一对象,导致操作一个元素而影响其他元素影响整个容器。。。

std::auto_ptr这种智能指针的特性,决定了它不适合作为容器的元素的。比如用于vector时,使用push_back(),调用的是复制构造函数。
但auto_ptr在拷贝构造的同时,把原有对象的实值拥有权转给了vector,同时删除了原有的auto_ptr。可能会导致后面使用中的错误。
当使用vector.clear()或者这个vector的生存周期到了,被释放的时候,同时会导致原有实值被删除!这往往不是我们想要的。

例如:

typedef auto_ptr<class T> aptr;
aptr p(new T);
vector<aptr> vec;
vec.push_back(p);//此时p被删除,vec.at(0)拥有了原实值
vec.clear();//原实值彻底被删除
p->operation();//还想用p做啥都要崩溃了
int a=;
int *p=&a;
int *q=&a;
vector <int*> vec1,vec2;
vec1.push_back(p);
vec2.push_back(p);

vec1和vec2中都有p,也就是a的地址,但vector并没有获得a的实值的拥有权!
这里vec1和vec2消逝或者是clear都不会导致a的消亡。

容器在存入数据的时候,是存入数据值的一个拷贝,而不是存入的数据的地址。比如说对象a,
存入容器,容器有一个a的拷贝_a,那么_a和a是互相独立的。对容器内_a的操作不会影响a,以上就是
STL容器的概念和”值“的语意。

c++ STL 常用容器元素类型相关限制 指针 引用的更多相关文章

  1. C++ STL常用容器浅析

    首先要理解什么是容器,在C++中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对象的指针,这种对象类型就叫做容器.简单来说 容器就是包含其他类的对象们的对象,当然这种(容器) ...

  2. 【C++】STL常用容器总结之五:双端队列deque

    6.双端队列deque 所谓的deque是”double ended queue”的缩写,双端队列不论在尾部或头部插入元素,都十分迅速.而在中间插入元素则会比较费时,因为必须移动中间其他的元素.双端队 ...

  3. 【Example】C++ STL 常用容器概述

    前排提醒: 由于 Microsoft Docs 全是机翻.所以本文表格是我人脑补翻+审校. 如果有纰漏.模糊及时评论反馈. 序列式容器 序列容器是指在逻辑上以线性排列方式存储给定类型元素的容器. 这些 ...

  4. C++ STL常用容器基本用法汇总

    1.vector 包含头文件#include<vector> 使用命名域using namespace std 定义元素类型为T的vector vector<T> vec 增: ...

  5. C++中STL常用容器的优点和缺点

    我们常用到的STL容器有vector.list.deque.map.multimap.set和multiset,它们究竟有何区别,各自的优缺点是什么,为了更好的扬长避短,提高程序性能,在使用之前需要我 ...

  6. STL常用容器使用方法

    在程序头部使用#include<stack>来引入STL的stack容器,然后使用stack<int> s语句来声明一个管理整型数据的容器s.stack常用成员函数:push( ...

  7. C++中STL常用容器的区别(转)

    我们常用到的STL容器有vector.list.deque.map.multimap.set和multiset,它们究竟有何区别,各自的优缺点是什么,为了更好的扬长避短,提高程序性能,在使用之前需要我 ...

  8. STL常用容器用法

    -1. 本文章中所有函数原型均为C++98的标准. 通用的操作 //遍历容器--以vector,map为例 vector<int> vt; map<int,int> mp; f ...

  9. 转载:STL常用容器的底层数据结构实现

    转载至:https://blog.csdn.net/qq_28584889/article/details/88763090 vector :底层数据结构为数组,支持快速随机访问 list:底层数据结 ...

随机推荐

  1. 【模考】2018.04.08 Travel

    Description 有N个人出去旅行,第i个人去A国有Ai种游玩方式,去B国有Bi种游玩方式,问至少有C个人去A国的情况下,所有人的游玩方式有多少种不同的可能. 两种所有人的游玩方式不同当且仅当存 ...

  2. 51nod 1571 最近等对 | 线段树 离线

    51nod 1571 最近等对 题面 现在有一个序列 a1, a2, ..., an ,还有m个查询 lj, rj (1 ≤ lj ≤ rj ≤ n) .对于每一个查询,请找出距离最近的两个元素 ax ...

  3. 跟踪分析Linux内核的启动过程--20135334赵阳林

    解决ubuntu下make menuconfig错误问题 http://blog.sina.com.cn/s/blog_726684020100r1oo.html 安装好相关的软件之后,键入make ...

  4. MyBatis.1入门篇

    一:简介 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...

  5. poi excel导入纯数字单元格显示科学计数法的处理

    POI读取Excel文件时,对纯数字单元格的处理   用POI读取Excel文件的时候,可能会遇到这样的问题:Excel文件中某一单元格中的数据为数字,例如12345678910123. 正常读取的话 ...

  6. struts2的MVC模式

    MVC是一种架构型模式,它本身并不引入新的功能,只是用来指导我们改善应用程序的架构,使得应用的模型和视图相分离,从而得到更好的开发和维护效率. 在MVC模式中,应用程序被划分成了模型(Model).视 ...

  7. Spss22安装与破解步骤

    Spss22安装与破解教程 向师姐请教了一些学术问题,哈哈说的有点大,不过真的很感谢,学到了很多,少走了很多弯路. 1.下载安装包 可以去IBM官网.人大论坛等网站下载,全部文件应包括spss22安装 ...

  8. linux那些事

    useradd -m -d /home/changp -Gusers,dialout,video account_name 创建新的账号 passwd account_name 修改指定账号的密码

  9. php 通过链接生成二维码,扫码支付用到

    $(".good_info").on('click',function () { var id = $(this).data('id'); var string='http://q ...

  10. label和fieldset标签

    一.label标签 作用:可以通过for属性关联input标签的 id 属性,这样可以实现在点击label标签的内容时,可以使input文本框中获取输入的光标. <body> <la ...