使用两种数据类型作为参数堆栈STL

时间:2012-10-04 14:37:19

标签: c++ stack

此程序取自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>>

5 个答案:

答案 0 :(得分:3)

退房:http://www.sgi.com/tech/stl/stack.html

为模板创建一个包含两个数据类型参数的堆栈stack<T, Sequence> stack;

完成是因为第一个类型参数是堆栈所包含的元素类型,第二个类型参数是用于实现堆栈的容器类型。

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

从该链接:

  

Stack是一个容器适配器,意味着它是在上面实现的   一些底层容器类型。默认情况下,底层类型是   deque,但可以明确选择不同的类型。

答案 1 :(得分:2)

重点是stack不是容器,而是容器适配器

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

另见What are Containers/Adapters? C++

为什么它们不是容器,请查看Container Adapters do not support iterators,其中举例说明了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=...>),因此适配器用户无法对其进行微调
  • 并非所有有效容器都具有相同数量和类型的模板参数

答案 2 :(得分: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. 它不是简单而简单的。如果我只想要一堆int s,我必须自己想一个容器,我不能只说my_stack<int>

  2. 它对容器施加约束,即它公开成员类型value_type。我不能说my_stack<my_insane_container<int>>

  3. 现在,您可以通过以下方式克服第二次投诉:

    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;
    
        // ...
    };
    

    但是现在你让它变得更加疯狂:容器现在需要成为一个模板(即再见class my_specialized_int_container),它需要 值键入作为第一个元素(即再见堆栈的堆栈)。

    因此,简而言之,标准库设计非常合理。

答案 3 :(得分:1)

你不能把stack<vector<T> >用来表示使用向量作为底层类的T的堆栈的原因仅仅是因为它具有不同的含义,它将是T的向量堆栈。你会期望它意味着那不是吗?向量是堆栈的有效值类型,您可以将向量推送到堆栈然后将其弹回...所以没有理由为什么标准会(部分地)专门化这个特定的模板参数。

答案 4 :(得分:0)

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