最終更新:2026-10-12
STL queue と stack ソースコード解析¶
0.はじめに¶
なぜstackとqueueはコンテナと呼ばれないのでしょうか?
本節では、この問いを持ってソースコードの深部に入り、分析していきます。
1.stack¶
stackのソースコードで注目すべき点は2つあります:
- デフォルトの_Sequenceはdequeである
- 内部の関数実装は_Sequenceの対応するコンテナの関数を呼び出している。

template<typename _Tp, typename _Sequence = deque<_Tp> >
class stack
{
public:
typedef typename _Sequence::value_type value_type;
typedef typename _Sequence::reference reference;
typedef typename _Sequence::const_reference const_reference;
typedef typename _Sequence::size_type size_type;
typedef _Sequence container_type;
protected:
// See queue::c for notes on this name.
_Sequence c;
public:
reference
top()
{
__glibcxx_requires_nonempty();
return c.back();
}
void
push(const value_type& __x)
{ c.push_back(__x); }
}
stackの基盤コンテナをテストする
stackの場合、基盤コンテナにはvector、deque、listを使えますが、map、setは使えません。
コンパイラは網羅的なチェックを行わないため、呼び出す関数が存在しないときに初めてコンパイルが通らなくなります。したがって、setのように基盤コンテナとして使えないものであっても、一部の関数を持っていれば呼び出し自体は成功し、呼び出す関数が存在しなくなって初めて失敗します。
int test_stack() {
cout<<"============test_stack============="<<endl;
clock_t timeStart = clock();
stack<int, list<int>> c;
for (long i = 0; i < 100000; i++)
c.push(i+1);
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
cout << "use stack milli-seconds : " << (clock() - timeStart) << endl;
timeStart=clock();
stack<int, deque<int>> c1;
for (long i = 0; i < 100000; i++)
c1.push(i+1);
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.top()= " << c1.top() << endl;
c1.pop();
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.top()= " << c1.top() << endl;
cout << "use stack milli-seconds : " << (clock() - timeStart) << endl;
// vector可以作为stack的底层容器
stack<int, vector<int>> c2;
for (long i = 0; i < 100000; i++)
c2.push(i+1);
cout << "stack.size()= " << c2.size() << endl;
cout << "stack.top()= " << c2.top() << endl;
c2.pop();
cout << "stack.size()= " << c2.size() << endl;
cout << "stack.top()= " << c2.top() << endl;
cout << "use stack milli-seconds : " << (clock() - timeStart) << endl;
}
2.queue¶
queueのソースコードで注目すべき点は2つあります:
- デフォルトの_Sequenceはdequeである
- 内部の関数実装は_Sequenceの対応するコンテナの関数を呼び出している。
template<typename _Tp, typename _Sequence = deque<_Tp> >
class queue
{
public:
typedef typename _Sequence::value_type value_type;
typedef typename _Sequence::reference reference;
typedef typename _Sequence::const_reference const_reference;
typedef typename _Sequence::size_type size_type;
typedef _Sequence container_type;
protected:
_Sequence c;
public:
void push(const value_type& __x)
{ c.push_back(__x); }
void pop()
{
__glibcxx_requires_nonempty();
c.pop_front();
}
}

同様に、優先度付きキューはvectorをデフォルトコンテナとして使用します。
template<typename _Tp, typename _Sequence = vector<_Tp>,
typename _Compare = less<typename _Sequence::value_type> >
class priority_queue
{
public:
typedef typename _Sequence::value_type value_type;
typedef typename _Sequence::reference reference;
typedef typename _Sequence::const_reference const_reference;
typedef typename _Sequence::size_type size_type;
typedef _Sequence container_type;
protected:
// See queue::c for notes on these names.
_Sequence c;
_Compare comp;
public:
reference
top()
{
__glibcxx_requires_nonempty();
return c.front();
}
void
push(const value_type& __x)
{
c.push_back(__x);
std::push_heap(c.begin(), c.end(), comp);
}
}

この2つのコンテナアダプタがサポートする基盤コンテナをテストします:
queue
queueの基盤コンテナはdequeでもlistでも構いませんが、vector、map、setは使えません。デフォルトのdequeを使うのが、挿入の面で他のコンテナを基盤にするよりも速いです!
int test_queue() {
cout<<"============test_queue============="<<endl;
clock_t timeStart = clock();
queue<int, list<int>> c;
for (long i = 0; i < 100000; i++) {
c.push(i+1);
}
cout << "stack.size()= " << c.size() << endl;
cout << "stack.front()= " << c.front() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.front()= " << c.front() << endl;
cout << "use list milli-seconds : " << (clock() - timeStart) << endl;
timeStart=clock();
queue<int, deque<int>> c1;
for (long i = 0; i < 100000; i++) {
c1.push(i+1);
}
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.front()= " << c1.front() << endl;
c1.pop();
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.front()= " << c1.front() << endl;
cout << "use deque milli-seconds : " << (clock() - timeStart) << endl;
}
priority_queue
優先度付きキューについては、テスト結果から、dequeを採用する方がデフォルトのvectorよりも挿入速度が速いことがわかりました!
基盤としてサポートされるのはvector、dequeコンテナで、list、map、setはサポートされません。
int test_priority_queue() {
cout<<"============test_priority_queue============="<<endl;
clock_t timeStart = clock();
priority_queue<int, deque<int>> c1;
for (long i = 0; i < 100000; i++) {
c1.push(i+1);
}
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.top()= " << c1.top() << endl;
c1.pop();
cout << "stack.size()= " << c1.size() << endl;
cout << "stack.top()= " << c1.top() << endl;
cout << "use deque milli-seconds : " << (clock() - timeStart) << endl;
priority_queue<int, vector<int>> c2;
for (long i = 0; i < 100000; i++)
c2.push(i+1);
cout << "stack.size()= " << c2.size() << endl;
cout << "stack.top()= " << c2.top() << endl;
c2.pop();
cout << "stack.size()= " << c2.size() << endl;
cout << "stack.top()= " << c2.top() << endl;
cout << "use stack milli-seconds : " << (clock() - timeStart) << endl;
}
そのため、stack、queue、priority_queueはコンテナとは呼ばれず、コンテナアダプタと呼ばれます。
関連トピック¶
- STL array ソースコード解析 | C++那些事
- STL string 深入解析 | C++那些事
- STL string 面接問題解説 | C++那些事
- STL deque ソースコード解析 | C++那些事
- STL 空基底クラス最適化 EBO | C++那些事
- STL 手書きハッシュテーブル実装 | C++那些事
- STL hashtable ハッシュテーブル | C++那些事
- STL イテレータソースコード解析 | C++那些事
- STL list ソースコード解析 | C++那些事
- STL map と multimap | C++那些事