此程序取自cplusplus.com
#include <iostream>
#include <vector>
#include <deque>
#include <stack>
using namespace std;
int main ()
{
deque<int> mydeque (3,100); // deque with 3 elements
vector<int> myvector (2,200); // vector with 2 elements
stack<int> first; // empty stack
stack<int> second (mydeque); // stack initialized to copy of deque
stack<int,vector<int> > third; // empty stack using vector
stack<int,vector<int> > fourth (myvector);
cout << "size of first: " << (int) first.size() << endl;
cout << "size of second: " << (int) second.size() << endl;
cout << "size of third: " << (int) third.size() << endl;
cout << "size of fourth: " << (int) fourth.size() << endl;
return 0;
}
我不明白的是,为什么我们提到stack<int, vector<int>>
,即两种数据类型,而不仅仅是stack<vector<int>>
?
退房:http://www.sgi.com/tech/stl/stack.html
创建一个具有两个数据类型参数的堆栈到模板,如stack<T, Sequence> stack;
因为第一个类型参数是堆栈所包含的元素的类型,而第二个类型参数则是用于实现堆栈的容器类型。
使用不同的容器类型可以为您提供不同的内存分配、速度方面的优点和缺点等。这只是在您希望使用的实现类型方面为您作为消费者提供了更大的灵活性。
来自该链接:
Stack是一个容器适配器,这意味着它是在一些底层容器类型。默认情况下,基础类型为deque,但是可以显式地选择不同的类型。
重要的一点是stack
不是容器,而是集装箱适配器。
在C++中,容器适配器是用于给定容器的附加接口。适配器使用的标准容器在一般情况下工作良好,但有时您可能希望使用不同的底层数据结构。
另请参阅什么是容器/适配器?C++
关于它们不是容器的原因,请查看Container Adapters不支持迭代器,例如stack
不提供迭代器。
额外知识:模板程序员可能会问"为什么第二个参数不是模板模板参数,比如
template <typename T, template <typename, typename> class Seq >
struct stack {};
#include <vector>
int main () {
stack<int, std::vector> s;
}
?">
快速回答:这将大大降低适配器类的能力。
- 适配器类必须决定容器使用的分配器(
vector
的完整签名是std::vector<T, Alloc=...>
),因此适配器用户无法对其进行微调 - 并非所有有效容器都具有相同数量和类型的模板参数
这正是标准库容器模板的设计方式:第一个模板参数是所包含数据的类型(或者对于关联容器,第一个两个)。
没有什么可以阻止你以不同的方式设计自己的模板,例如,就像你建议的那样:
template <typename Backend>
class my_stack
{
public:
typedef Backend container_type;
typedef typename container_type::value_type value_type;
private:
container_type container;
// ...
};
然而,这种设计有两个缺点:
这不是最小和简单的。如果我只想要一堆
int
,我必须自己考虑一个容器,我不能只说my_stack<int>
。它对容器施加约束,即它公开一个成员类型
value_type
。我不能说my_stack<my_insane_container<int>>
。
现在,您可以通过以下方式克服第二次投诉:
template <typename> class my_crazy_stack;
template <template <typename ...> class Tmpl, typename T, typename ...Args>
class my_cazy_stack<Tmpl<T, Args...>>
{
public:
typedef Tmpl<T, Args...> container_type;
typedef T value_type;
// ...
};
但现在你让它变得更加疯狂:容器现在需要成为一个模板(即bye-byeclass my_specialized_int_container
),它需要将其值类型作为第一个元素(即bye bye堆栈)。
总之,标准库的设计是非常合理的。
不能将stack<vector<T> >
表示使用向量作为底层类的T的堆栈,只是因为它有不同的含义,即T的向量堆栈?向量是堆栈的有效值类型,您可以将向量推到堆栈上,然后将其弹出。。。因此,标准没有理由(部分)专门化这个特定的模板参数。
Stack不是STL容器,而是适配器,这是编程模式之一。简而言之,这意味着,该堆栈用于包装容器(vector
或deque
),以"替换"其公共方法(创建新的公共方法并隐藏现有方法)。您可以在此处阅读有关适配器的更多信息http://en.wikipedia.org/wiki/Adapter_pattern