为什么我不能使用大括号括起来的初始值设定项列表构造队列/堆栈?(C++11)
Why can't I construct a queue/stack with brace-enclosed initializer lists? (C++11)
Program 1:
#include <iostream>
#include <cstdlib>
#include <vector>
int main(){
//compiles successfully
std::vector<int> vec{1,2,3,4,5};
return EXIT_SUCCESS;
}
计划2:
#include <iostream>
#include <cstdlib>
#include <queue>
int main(){
//compiler error
std::queue<int> que{1,2,3,4,5};
return EXIT_SUCCESS;
}
错误信息:
main.cpp: In function ‘int main()’:
main.cpp:7:31: error: no matching function for call to ‘std::queue<int>::queue(<brace-enclosed initializer list>)’
main.cpp:7:31: note: candidates are:
/usr/include/c++/4.6/bits/stl_queue.h:141:7: note: std::queue<_Tp, _Sequence>::queue(_Sequence&&) [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]
/usr/include/c++/4.6/bits/stl_queue.h:141:7: note: candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:137:7: note: std::queue<_Tp, _Sequence>::queue(const _Sequence&) [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]
/usr/include/c++/4.6/bits/stl_queue.h:137:7: note: candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: std::queue<int>::queue(const std::queue<int>&)
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: std::queue<int>::queue(std::queue<int>&&)
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: candidate expects 1 argument, 5 provided
问题:
为什么队列不能像向量一样初始化?
我想它们不是序列容器,但这有什么关系呢?
我确信有一个很好的理由,但我找不到任何解释。
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
queue<int> q({1, 2, 3});
我认为它与容器适配器而不是容器没有任何关系(尽管我承认我不确定为什么省略了正确的构造函数)。
当您将带支撑的初始值设定项列表与 std::vector
一起使用时,您将使用此(C++11 中的新功能)构造函数:
vector(initializer_list<T>, const Allocator& = Allocator());
查看std::queue
的定义,可用的构造函数是:
explicit queue(const Container&);
explicit queue(Container&& = Container());
template <class Alloc> explicit queue(const Alloc&);
template <class Alloc> queue(const Container&, const Alloc&);
template <class Alloc> queue(Container&&, const Alloc&);
template <class Alloc> queue(const queue&, const Alloc&);
template <class Alloc> queue(queue&&, const Alloc&);
采用initialization_list的构造函数明显不存在。
我很确定,尽管它是一个容器适配器,但如果需要,这样的构造函数将是微不足道的。举个例子:
#include <deque>
#include <initializer_list>
#include <iostream>
template <class T, class container=std::deque<T> >
class myqueue {
container data;
public:
explicit myqueue(std::initializer_list<T> t) : data(t) {}
void pop() { data.pop_front(); }
T front() const { return data.front(); }
bool empty() const { return data.empty(); }
};
int main(){
myqueue<int> data {1, 2, 3, 4};
while (!data.empty()) {
std::cout << data.front() << "n";
data.pop();
}
return 0;
}
G++ 4.7 毫无问题地接受了这一点,并完全生成了你期望的输出:
1
2
3
4
虽然我没有用任何其他编译器进行测试,但我看不出其他编译器有任何理由不能很好地使用它(当然,前提是它们实现了必要的功能)。
编辑:我刚刚浏览了一些委员会文件,建议在C++中添加initalizer_lists(例如,N1890,N1919,N2100,N2215,N2220),在我看来,这就像一个简单的疏忽。许多早期的论文更具概念性,但 N2220 为工作文件提供了相当多的拟议语言。对于std::array
(例如),它特别指出不需要更改。然后它经过deque
、vector
、[unordered_][multi_](set|map)
,并显示每个更改所需的更改 - 但根本没有提到堆栈或队列,在任何一个方向上。没有提议增加对std::initializer_list
的支持,也没有(像std::array
一样)省略的理由。
我的结论是,这是一个简单的疏忽,可能由于两个原因而溜走了:1)适配器几乎是容器,但不完全是容器,2)适配器类似乎没有被大量使用,所以忘记它们可能相当容易(当然,还有普遍存在的第三个原因:大多数活跃的委员会成员都非常过度劳累)。
Edit2:我可能应该再补充一个细节:由于stack
和queue
都可以接受另一个容器进行初始化,因此您可以轻松地执行以下操作:
std::stack<int> data(std::vector<int>{1,2,3,4});
这有点冗长,但不太可能导致任何效率损失(容器将作为右值引用传递,因此其表示将被"窃取"而不是复制)。但有一个警告:如果你使用的容器类型与容器适配器底层的容器不匹配,你将获得副本而不是移动(因此,可能会失去一些效率)。
std::queue
和std::stack
实际上不是容器,它们是使用容器的所谓容器适配器(默认为std::deque
)。因此,不能将其初始化为其他容器。
编辑
要使容器能够使用初始值设定项列表,它必须具有将std::initializer_list
作为参数的构造函数。容器适配器不这样做。如果是故意的或对标准委员会的监督取决于任何人的解释。
- 如何从队列插入到 2D 列表
- 在使用链接列表实施队列时,为什么插入复杂性o(1)
- 使用队列和列表 STL 进行C++分配。在将数据填充到列表或队列中然后打印该数据时遇到问题
- 队列顺序中的链接列表
- 将双重链接列表与C 中的堆栈和队列类链接
- 队列实现,带有C 中的链接列表
- C - 推回队列列表
- C++ 链接列表队列实现和析构函数错误:"Aborted (Core Dumped)"
- c2955 - 使用类模板 reuires 参数列表.队列
- 生产者-消费者队列 - std::queue 或用户编写的链接列表
- 为什么我不能使用大括号括起来的初始值设定项列表构造队列/堆栈?(C++11)
- 如何在链接列表队列中将一些数据从一个节点传输到另一个节点C++
- 如何在c++中动态创建一个具有列表底层数据结构的队列
- 具有列表容器的优先级队列
- 为优先级队列的基础容器使用自定义类型的列表
- 将项目从列表移动到堆栈或队列
- 用双链表构建一个学生列表队列
- 正在处理由双链接列表组成的学生队列
- 如何从具有相应优先级队列的列表中删除元素
- 无法使用基础列表推送到队列