4

本程序取自 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>>ie 两种数据类型而不仅仅是stack<vector<int>>

4

5 回答 5

3

查看:http ://www.sgi.com/tech/stl/stack.html

像这样为模板创建具有两个数据类型参数的堆栈stack<T, Sequence> stack;

之所以这样做,是因为第一个类型参数是堆栈所持有的元素的类型,第二个类型参数是用于实现堆栈的容器类型。

使用不同的容器类型会在速度等方面为您提供不同的内存分配、优点和缺点。它只是在您希望使用的实现类型方面为消费者提供更多的灵活性。

从那个链接:

Stack 是一个容器适配器,这意味着它是在一些底层容器类型之上实现的。默认情况下,底层类型是双端队列,但可以显式选择不同的类型。

于 2012-10-04T14:43:03.313 回答
2

重要的一点是,stack它不是一个容器,而是一个容器适配器

在 C++ 中,容器适配器是给定容器的附加接口。适配器使用的标准容器在一般情况下运行良好,但有时您可能希望使用不同的底层数据结构。

另请参阅什么是容器/适配器?C++

关于为什么它们不是容器,请查看Container Adapters do not support iterators,这说明了 egstack不提供迭代器。


额外知识:模板程序员可能会问“为什么第二个参数不是模板模板参数,比如

template <typename T, template <typename, typename> class Seq >
struct stack {};

#include <vector>

int main () {
    stack<int, std::vector> s;
}

?”

快速回答:这将大大降低适配器类的能力。

  • 适配器类必须决定容器使用的分配器(vectoris的完整签名std::vector<T, Alloc=...>),因此适配器用户无法对其进行微调
  • 并非所有有效容器都具有相同数量和类型的模板参数
于 2012-10-05T08:58:19.730 回答
1

这正是标准库容器模板的设计方式:第一个模板参数是包含数据的类型(或前两个用于关联容器)。

没有什么可以阻止您以不同的方式设计自己的模板,例如,就像您建议的那样:

template <typename Backend>
class my_stack
{
public:
    typedef Backend                         container_type;
    typedef typename container_type::value_type value_type;

private:
    container_type container; 

    // ...
};

但是,这种设计有两个缺点:

  1. 这不是最小和简单的。如果我只是想要一堆ints,我必须自己想一个容器,我不能只说my_stack<int>

  2. 它对容器施加约束,即它公开一个成员类型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 bye class my_specialized_int_container),并且它需要将值类型作为第一个元素(即 bye bye stack of stacks)。

所以,简而言之,标准库的设计是相当明智的。

于 2012-10-04T16:32:52.433 回答
1

您不能stack<vector<T> >使用向量作为底层类来表示一堆 T 的原因仅仅是因为它具有不同的含义,即 T 的向量堆栈。您会期望它的意思不是吗?向量是堆栈的有效值类型,您可以将向量推入堆栈然后将其弹出...因此,标准没有理由(部分)专门化此特定模板参数。

于 2012-10-05T09:16:51.107 回答
0

Stack 不是 STL 容器,而是适配器,是编程模式之一。简而言之,这意味着该堆栈用于包装容器(vectordeque)以“替换”其公共方法(创建新的公共方法并隐藏现有方法)。您可以在此处阅读有关适配器的更多信息http://en.wikipedia.org/wiki/Adapter_pattern

于 2012-10-04T14:46:19.193 回答