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. Java并发编程之线程生命周期、守护线程、优先级、关闭和join、sleep、yield、interrupt

    Java并发编程中,其中一个难点是对线程生命周期的理解,和多种线程控制方法.线程沟通方法的灵活运用.这些方法和概念之间彼此联系紧密,共同构成了Java并发编程基石之一. Java线程的生命周期 Jav ...

  2. Java代码中谁拿到了锁?

    我们都知道当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁.这些基础也许大家都知道,但是很多人还是搞不清哪个对象才是锁?如果你能正确回答以下问题,那么才算你彻底搞明白了哪个 ...

  3. 关于nginx的一点记录

    (1) 安装nginx官网下载:http://nginx.org下载适合Windows的安装包,是一个压缩包,直接解压就可以了. (2) 启动nginx有三种方式启动:a. 双击nginx.exe图标 ...

  4. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  5. zookeeper和PHP zookeeper和kafka 扩展安装

    http://blog.csdn.net/fenglailea/article/details/52458737#t3   目录(?)[-] 安装zookeeper 1直接安装zookeeper无须编 ...

  6. MVP, MVVM In Android

    MVP, MVVM In Android(新手必看)安卓MVP的理解,看完你就会用mvp了 - zq019的博客 - 博客频道 - CSDN.NEThttp://blog.csdn.net/zq019 ...

  7. 【bzoj4264】小C找朋友

    题解 $a$和$b$是好*友说明除了这两个人以外的邻接集合相同: 做两次$hash$,分别都处理和$a$相邻的点排序$hash$,①$a$要算进$a$的相邻集合,②$a$不算进: 当两个人不是好*友, ...

  8. JavaWeb中的多数据源开发

    从我们接触Javaweb开始,ssh框架或者ssm等或许是惊叹于框架的强大之处还是自身的迷茫,一直没有注意到一个问题就是:在我的项目中在spring中所配置的数据源都是指向单一数据库,都是单数据源,一 ...

  9. E. Turn Off The TV Educational Codeforces Round 29

    http://codeforces.com/contest/863/problem/E 注意细节 #include <cstdio> #include <cstdlib> #i ...

  10. 21天实战caffe笔记_第一天

    1 深度学习术语 深度学习常用名词:有监督学习.无监督学习.训练数据集.测试数据集.过拟合.泛化.惩罚值(损失loss); 机器自动学习所需三份数据:训练集(机器学习的样例),验证集(机器学习阶段,用 ...