C++ 为什么std::配对<;常数int,int>;不适用于某些STL容器?

C++ 为什么std::配对<;常数int,int>;不适用于某些STL容器?,c++,c++11,stl,C++,C++11,Stl,似乎有些容器接受std::pair作为值类型,但有些容器不接受。问题当然出在const部分 我在谷歌上搜索了一下,发现只有std::vector需要拷贝可分配的数据。然而,std::pair与std::vector、std::set和std::list(可能还有其他容器)配合使用效果很好,但与std::map和std::priority_queue配合使用效果不好(后者真的让我讨厌) 以下编译没有问题(gcc 6.1.0) std::vector; vector.push_back(std::m

似乎有些容器接受
std::pair
作为值类型,但有些容器不接受。问题当然出在
const
部分

我在谷歌上搜索了一下,发现只有
std::vector
需要拷贝可分配的数据。然而,
std::pair
std::vector
std::set
std::list
(可能还有其他容器)配合使用效果很好,但与
std::map
std::priority_queue
配合使用效果不好(后者真的让我讨厌)

以下编译没有问题(gcc 6.1.0)

std::vector;
vector.push_back(std::make_pair(3,5));
std::set;
设置插入(标准::制作配对(3,5));
std::列表;
列表。推回(std::生成一对(3,5));
但这会导致编译错误:

std::priority_queue<std::pair<const int, int>> pq;
pq.push(std::make_pair(3, 5));
std::map<int, std::pair<const int, int>> map;
map[2] = std::make_pair(3, 5);
std::优先级队列pq;
产品质量推送(标准:制造(3,5)对);
地图;
map[2]=std::make_对(3,5);
错误:分配只读成员'std::pair::first'
这背后的原因是什么?如果
std::map
std::set
具有相同的底层实现,那么它们不应该具有相同的行为吗?尽管它需要移动数据,但为什么它能与std::vector一起工作?

问题 让我们更深入地了解您的错误:

错误:分配只读成员“std::pair::first”

解决方案 这是没有办法的!正如您在这里看到的,有一个成员仅处于读取模式

 std::priority_queue<std::pair<const int, int>> pq;
std::优先级队列pq;
在这里您可以看到
const int
。嗯,
const
修饰符使变量只能处于读取模式,并且不能更改!这是你的问题。如果您试图分配一个常数,那么这会导致一个错误,因为您试图在常数处于只读模式时更改该常数

工具书类
任何需要分配的任务都将中断


  • vector::push_back
    不需要赋值,只需要复制/移动构造
  • set::insert与之相同
  • 列表同上::向后推
  • priority\u queue::push
    需要在现有元素周围移动以维护heap属性(通过
    std::push\u heap
    ),这需要赋值
  • map[2]=stuff实际上是一个赋值。如果您想让它工作,请使用
    map::insert
    map::emplace

容器的设计不包含
const
元素。我不理解你的困惑。您正在尝试赋值,并抱怨无法赋值给常量。@S.K.:
vector[0]=std::make_pair(3,5)也不行。@KerrekSB我不是在抱怨,我只是想了解为什么不同的容器行为不同,以及这是否是一种预期的行为。这些容器是为非常量内容编写的,而您得到的行为大多是巧合的,这取决于库编写者在实现非常量变体时所做的事
vector::push_back
实际上需要移动元素。@Slava它是重新分配时的复制/移动构造,而不是赋值。@Slava它是。我在哪里说过不需要?那么我不明白为什么
std::vector
移动元素不需要赋值,而
std::push_heap
则需要赋值。从向量或deque中删除元素也需要赋值。
error: assignment of read-only member ‘std::pair<const int, int>::first’
 std::priority_queue<std::pair<const int, int>> pq;