1、容器的定义
容器:专门用于某种形式组织及存储数据的类称为“容器”。
 
2、容器与迭代器
迭代器:封装了对容器虚拟数据序列的操作并按约定提供统一界面以遍历容器内容的代理类即为迭代器。
 
举例理解:
template<typename T> class list;

template<typename T>
struct list_node
{
typedef T value_type;
typedef T& reference_type;
typedef const T const_reference_type; T value;
list_node *prev;
list_node *next; list_node(T const &value, list_node *prev, list_node *next) :
value(value), prev(prev), next(next){}
}; template<typename N>
class list_iterator
{
N *pos;
template<typename T> friend class list; public:
typedef typename N::value_type value_type;
typedef typename N::reference_type reference_type;
typedef typename N::const_reference_type const_reference_type;
typedef list_iterator<N> self_type; list_iterator() :pos(){}
list_iterator(N *pos) :pos(pos){} bool operator != (self_type const &right) const{
return pos != right.pos;
} bool operator == (self_type const &right) const{
return pos != right.pos;
} self_type& operator++(){
if (pos) pos = pos->next;
return *this;
} reference_type operator * () throw (std::runtime_error){
if (pos) return pos->value;
else throw (std::runtime_error("null iterator!\n"));
}
}; template<typename T>
class list
{
typedef list_node<T> node_type;
node_type *head; public:
typedef T value_type;
typedef list_iterator<node_type> iterator; list() :head(){}
~list(){
while (head)
{
node_type *n = head;
head = head->next;
delete n;
}
} void push_front(T const &v)
{
head = new node_type(v, , head);
if (head->next)
{
head->next->prev = head;
}
} void pop_front(T const &v)
{
if (head)
{
node_type *n = head;
head = head->next;
head->prev = ;
delete n;
}
} void insert(iterator it, T const &v)
{
node_type *n = it.pos;
if (n)
{
node_type *new_node = new node_type(v, n, n->next);
new_node->next->prev = new_node;
n->next = new_node;
}
} void erase(iterator &it)
{
node_type *n = it.pos;
++it;
if (n)
{
if (n->next)
{
n->next->prev = n->prev;
}
if (n->prev)
{
n->prev->next = n->next;
}
if (head == n)
{
head = n->next;
}
delete n;
}
} bool is_empty() const { return head == ; }
iterator begin(){ return iterator(head); }
iterator end(){ return iterator(); }
};
针对树形结构节点类型的迭代器:
template<typename T>
struct tree_node
{
typedef T value_type;
typedef T& reference_type;
typedef const T& const_reference_type; T value;
tree_node *parent;
tree_node *left;
tree_node *right; tree_node(T const &value,
tree_node *parent,
tree_node *left,
tree_node *right):
value(value),
parent(parent),
left(left),
right(right){} ~tree_node()
{
if (left) delete left;
if (right) delete right;
}
}; template<typename N>
class tree_iterator
{
const N *pos;
public:
typedef typename N::value_type value_type;
typedef typename N::const_reference_type const_reference_type;
typedef tree_iterator<N> self_type; tree_iterator() :pos(){}
tree_iterator(const N *pos) :pos(pos){} bool operator == (self_type const &right) const{
return pos == right.pos;
} self_type& operator ++ (){
if (pos){
if (pos->right){
pos = pos->right;
while (pos->left)
{
pos = pos->left;
}
}
else
{
while (pos->parent && (pos->parent->right == pos))
{
pos = pos->parent;
}
pos = pos->parent;
}
}
return *this;
} const_reference_type operator * () const throw(std::runtime_error)
{
if (pos)
{
return pos->value;
}
else
{
throw std::runtime_error("Null iterator!\n");
}
}
}; template<typename T>
class set
{
typedef tree_node<T> node_type;
node_type *root;
public:
typedef T value_type;
typedef tree_iterator<node_type> const_iterator; set() :root(){}
~set(){ if (root) delete root; } bool insert(T const &v)
{
node_type **n = &root;
node_type *p = ;
while (*n)
{
if (v == (*n)->value)
{
return false;
}
else
{
p = *n;
n = v < (*n)->value ? &((*n)->left) : &((*n)->right);
}
}
*n = new node_type(v, p, , );
return true;
} bool has(T const &v)
{
node_type *n = root;
while (n)
{
if (v == n->value)
return true;
n = v < n->value ? n->left : n->right;
}
return false;
} bool is_empty() const { return root == ; } const_iterator begin() const{
node_type *n = root;
while (n->left) n = n->left;
return const_iterator(n);
} const_iterator end() const { return const_iterator(); }
};
尽管容器内部的数据结构类型不同(set是一个树形结构,而list是链表结构),但是提供给用户的操作界面iterator的所有操作都是相同的,所以底层数据结构对用户来说是透明的。
这也算是一种设计思路。
 
3、迭代器和算法
利用迭代器求和:
template<typename C>
typename C::value_type
sum(C &c)
{
typedef typename C::value_type value_type;
typedef typename C::iterator iterator;
value_type sum(); for (iterator i = c.begin(); i != c.end(); ++i)
{
sum += *i;
}
return sum;
}
不足1:只能求所有元素之和,不能求部分元素之和。可以将一个迭代器改为两个迭代器来弥补这里的不足。
template<typename I>
typename I::value_type
sum(I begin, I end)
{
typedef typename I::value_type value_type; value_type sum();
for (; begin != end; ++begin)
{
sum += *begin;
}
return sum;
}
不足2:要兼容最原始的容器——数组。
这里的I都是某种类型的迭代器,你可以通过I::value_type获取迭代器所指的对象的类型。但是数组的指针是一个普通的指针,是没有value_type成员的。借助另外一个类模板及模板特例功能来统一描述迭代器指针的特性。
 
再进行一层封装,使得普通的指针也有了value_type:
template<typename I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; template<typename P>
struct iterator_traits<P*>
{
typedef P value_type;
};
改进后:
template<typename I>
typename iterator_traits<I>::value_type
sum(I begin, I end)
{
typedef typename iterator_traits<I>::value_type value_type; value_type sum();
for (; begin != end; ++begin)
{
sum += *begin;
}
return sum;
}
4、迭代器的陷阱
a、容器中通常有迭代器为参数对指定位置进行操作的成员函数,调用此类函数有个隐含要求,即迭代器所指数据来自该容器,否则后果无法预测。
b、由于迭代器独立于容器之外,用户可以一次性生成多个迭代器对容器内数据进行操作。这样就会产生冲突。

《深入实践C++模板编程》之五——容器与迭代器的更多相关文章

  1. 《深入实践C++模板编程》之六——标准库中的容器

    1.容器的基本要求 a.并非所有的数据都可以放进容器当中.各种容器模板对所存数据类型都有一个基本要求——可复制构造.将数据放进容器的过程就是通过数据的复制构造函数在容器内创建数据的一个副本的过程. b ...

  2. 《深入实践C++模板编程》之四——特例

    1. 所谓模板特例,是针对符合某种条件的模板参数值集合另外声明的模板实现变体. template<typename T> class my_vector; template<> ...

  3. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  4. 《深入实践C++模板编程》之二——模板类

    1.类的模板的使用 类,由于没有参数,所以没有模板实参推导机制. #include <stdexcept> template<typename T> class my_stac ...

  5. 《深入实践C++模板编程》之一——Hello模板

    1.通过一个简单的例子来理解模板的用途: 模板为不同类型的数据生成操作相同或相似的函数. 弱语言如Python,可以使用一种函数来应对各种类型,但是C++就不得不为不同的类型编写相似的函数.模板的作用 ...

  6. c++ 模板参数做容器参数迭代器报错 vector<T>::const_iterator,typename const报错

    错误1: template<class T>void temp(std::vector<T>& container){        std::vector<T& ...

  7. STL(标准模板库)理论基础,容器,迭代器,算法

    基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间.   ...

  8. C++之模板编程

    当我们越来越多的使用C++的特性, 将越来越多的问题和事物抽象成对象时, 我们不难发现:很多对象都具有共性. 比如 数值可以增加.减少:字符串也可以增加减少. 它们的动作是相似的, 只是对象的类型不同 ...

  9. c++ 基于Policy 的 模板编程

    在没真正接触c++  模板编程之前.真的没有想到c++ 还能够这么用.最大的感触是:太灵活了,太强大了. 最初接触模板威力还是在Delta3d中,感觉里面的模板使用实在是灵活与方便,特别是dtAI中使 ...

随机推荐

  1. python 文件压缩及解压

    文件压缩 import os import zipfile def zip_dir(dirname,zipfilename): """ | ##@函数目的: 压缩指定目录 ...

  2. Oracle 报错 ORA-03290的处置

    MySql 的tuancate命令是直接truncate tableName,但在Oracle需要写成truncate table tableName,改正就好了. --END-- 2019.10.1 ...

  3. [java]取当前平台默认字符集,取字符串长度

    public class TimestampLength { public static void main(String[] args) { System.out.println(java.nio. ...

  4. 使用预设半透明鼠标Cursor

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  5. LC 638. Shopping Offers

    In LeetCode Store, there are some kinds of items to sell. Each item has a price. However, there are ...

  6. driver.implicitly_wait不起作用的排错方法

    环境是python3.6+selenium 3.4.3+chrome64 在编写前端自动化脚本时使用implicitly_wait时不起作用 1.确认自己是否正确使用,可用简单的例子来测试,比如: 此 ...

  7. 控制器Controller

    1)  org.springframework.web.servlet.mvc.ParameterizableViewController 如果请求是/hello.action的请求路径,则直接跳转到 ...

  8. SQL语句之数据定义语言(DDL)详解

    操作对象:数据库 1)创建数据库 MariaDB [(none)]> help create databaseName: 'CREATE DATABASE'Description:Syntax: ...

  9. 九十七:CMS系统之模板抽离和个人信息页面

    模板抽取,将公共的页面抽出来作为模板 {% from 'common/_macros.html' import static %}<!DOCTYPE html><html lang= ...

  10. [CDH] Acquire data: Flume and Kafka

    Flume 基本概念 一.是什么 Ref: http://flume.apache.org/ 数据源获取:Flume.Google Refine.Needlebase.ScraperWiki.Bloo ...