std::Deque使用总结

版权声明:实不相瞒,我也想成为大佬 https://blog.csdn.net/CV_Jason/article/details/83023931

Deque

  Deque与Vector非常相似,它也采用dynamic array进行管理,提供随机访问,同时具有与vector一模一样的接口。不同的是Deque的dynamic array头尾都是开放的,因此可以在两端进行快速的插入和删除。
在这里插入图片描述
  为了提供这种能力,deque通常实现了一种独立区块(a bunch of individual blocks),第一区块朝某一方向扩展,最末区块朝另一方向扩展。
在这里插入图片描述
  使用Deque之前,必须包含头文件<deque>

	#include<deque>

  其中,deque的类型在std命名空间std内一个class template为:

template<
    class T,
    class Allocator = std::allocator<T>
> class deque;

  和vector相同,这里的T是为了template表明元素类型的,而Allocator则是指定内存模型(memory model)。

Deque的能力

  Deque与Vector相比,有所相同,又有所不同,下面是两者的异同点:
  相同之处
  1.支持随机访问,迭代器均属于random-access iterator;
  2.基于中间位置的元素的移除和插入,速度都比较慢,因为要进行大量元素的移动和复制操作;
  3.vector所支持的接口在deque上都能使用,且具有相同的效果。

  不同之处
  1.两端都能够进行快速的插入和移除操作
  2.访问deque时,内部结构会多一个间接过程,因此元素的访问以及迭代器的动作会相比vector较慢
  3.迭代器需要在不同的区块间进行跳转,因此迭代器必须是smart_pointer,不能是寻常pointer;
  4.Deque不支持对容量大小的控制,需要特别注意的是,除了首尾两端,在任何地点安插或者删除元素都会导致pointer、reference和iterator的失效;
  5.Deque重新分配内存优于vector,因为其内部结构显示,deque重新分配内存的时候,不需要复制所有的元素;
  6.Deque会释放不需要的内存块,Deque的大小是可缩减的,但是要不要这么做,如何做,取决于编译器。
  总结:显然,deque具有vector的特性,且比vector更强大,但C++之中,更强大的功能往往意味这更大的时空开销,如何在功能和开销上作取舍,取决于具体应用场景。

  Deque适用场景
  1.移除和插入操作发生在首尾两端(Deque的特性决定了该操作效率惊人);
  2.无须迭代器指向其元素(Deque扩容机制导致了其迭代器更容易失效);
  3.要求不再使用的元素必须释放(Deque能够释放不使用的内存块,但C++ standard并不保证这一点,依赖于编译器实现)。

Deque相关操作

构造、复制和销毁

  Deque的构造与析构函数,设计逻辑与Vector几乎相同。

序号 操作 效果
1 deque<Elem> c Deque默认构造函数,生成一个deque,没有任何元素
2 deque<Elem> c(c2)
deque<Elem> c=c2
Copy构造函数,支持深度拷贝
3 deque<Elem> c(rv)
deque<Elem> c=rv
Move构造函数,rv是右值引用(C++11新特性
4 deque<Elem> c(n) 生成一个大小为n的deque
5 deque<Elem> c(n,elem) 生成一个大的小为n的deque,并初始化元素为elem
6 deque<Elem> c(beg,end) 生成一个deque,以区间[beg,end)作为元素初值
7 deque<Elem> c(initlist) 生成一个deque,并以初值列进行初始化
8 c.~deque() 销毁所有元素,释放内存

非更易型操作(Nonmodifying Operating)

  与Vector相同,Deque的非更易型操作如下表所示:

序号 操作 效果
1 c.empty() 返回容器是否为空,为空则返回true,否则false
2 c.size() 返回目前元素的个数
3 c.max_size() 返回元素个数的最大可能量,即自动分配内存的极限
4 c.shrink_to_fit() 降低容量以符合元素个数(C++11新特性
5 c1==c2
c1!=c2
c1>c2
c1<c2
c1<=c2
c1>=c2
容器的比较操作都是基于每个元素的,即所有的元素都满足比较关系才返回true,否则是false
6 c[index] 返回索引index所指向的元素(不检查边界)
7 c.at(index) 返回索引index所指向的元素(检查边界,越界会抛出range-error异常)
8 c.front() 返回第一元素
9 c.back() 返回最末元素
10 c.begin() 返回一个random-access iterator,指向第一个元素
11 c.end() 返回一个random-access iterator,指向最后一个元素
12 c.cbegin() 返回一个const random-access iterator,指向第一个元素(C++11新特性
13 c.cend() 返回一个const random-access iterator,指向最后一个元素(C++11新特性
14 c.rbegin() 返回一个reverse iterator,指向第一个元素
15 c.rend() 返回一个reverse iterator,指向最后一个元素
16 c.crbegin() 返回一个const reverse iterator,指向第一个元素(C++11新特性
17 c.crend() 返回一个const reverse iterator,指向最后一个元素(C++11新特性

  举个例子——

	deque<int> c{ 1,2,3,4,5,6,7,8,9 };
	cout << "c.empty() = " << c.empty() << endl
		<< "c.size() = " << c.size() << endl
		<< "c.max_size()" << c.max_size() << endl;
	for (auto it = c.cbegin(); it != c.cend(); it++) {
		cout << *it << " ";
	}

在这里插入图片描述

更易型操作

  Deque的更易型操作,如下表所示:

序号 操作 效果
1 c = c2 将c2的数据复制给c,该复制是深度复制
2 c = rv 将rvalue rv的所有元素以move assignment的形式给c(C++11新特性
3 c = initlist 将初值列所有元素赋值给c(C++11新特性
4 c.assign(n,elem) 复制n个elem元素给c
5 c.assign(beg,end) 复制区间[beg,end)元素给c
6 c.assign(initlist) 复制初值列所有元素给c
7 c1.swap(c2)
swap(c1,c2)
置换c1和c2的数据
8 c.push_back(elem) 附加一个elem元素到deque末尾
9 c.pop_back() 移除末尾的一个元素,不返回任何值
10 c.push_front() 附加一个elem元素到首部
11 c.pop_front() 移除首部的一个元素,不返回任何值
12 c.insert(pos,elem) 在iterator指向的pos位置的前一个位置插入elem拷贝,并返回新元素的位置
13 c.insert(pos,n,elem) 在iterator指向的pos位置的前一个位置插入n个elem拷贝,并返回第一个新元素的位置
14 c.insert(pos,beg,end) 在iterator指向的pos位置的前一个位置插入区间[beg,end)所有元素拷贝,并返回第一个新元素的位置
15 c.insert(pos,initlist) 在iterator指向的pos位置的前一个位置插入initlist初值列拷贝,并返回第一个新元素的位置(C++11新特性)
16 c.emplace(pos,args…) 在iterator位置pos之前插入一个以args为初值的运输,并返回新元素的位置(C++11新特性
17 c.emplace_back(args…) 插入一个args初值于末尾,不返回任何东西(C++11新特性
18 c.emplace_front(args…) 插入一个args初值于首部,不返回任何东西(C++11新特性
19 c.erase(pos) 移除iterator位置pos的元素,返回下一个元素的位置
20 c.erase(beg,end) 移除区间[beg,end)区间内的所有元素,返回下一个元素的位置
21 c.resize(num) 将元素数量大小调整为num,如果数量比原始要大,那么多出来的部分用默认构造函数进行初始化
22 c.resize(num,elem) 将元素数量大小调整为num,如果数量比原始要大,那么多出来的部分用初始化为elem
23 c.clear() 移除所有元素,释放内存

异常控制

  Deque提供的异常处理是STL所定义的最低限度的异常处理,除了at函数会对边界进行检查,可能会抛出range-error异常之外,其他函数不会抛出任何标准异常,但编译器往往会加入自己的异常处理,比如VS所实现的STL版本就有诸多异常控制。

猜你喜欢

转载自blog.csdn.net/CV_Jason/article/details/83023931
今日推荐