C ++ std :: vector <std :: pair <const int,=“” int =“” >>无法插入元素

时间:2018-08-11 17:24:50

标签: c++ c++11

int main() {
  using kv = std::pair<const int ,int>;

  std::vector<kv> vec;
  kv a{1,1};
  vec.insert(vec.begin(),a);
}

我试图将元素插入该向量,但是编译器给出了此错误消息:

cannot assign to non-static data member 'first' with const-qualified type 'const int'

push_back()可以正确编译。为什么?将元素插入到这样的向量中的正确方法是什么?

添加: 我使用std::pair<const int, int>的原因是我想实现类似std::map的东西,并且不应修改键值对中的键。但是我不确定std::pair<const int, int>是否是执行此操作的正确方法。

2 个答案:

答案 0 :(得分:8)

让我们从观察以下内容开始:

std::pair<const int, int> a, b;

a=b;

这也不会编译。为什么?因为您实际上是在声明以下类:

class my_pair {

public:
    // ... Bunch of irrelevant stuff

    const int first;
    int second;
};

该类的默认赋值运算符已删除。默认的赋值运算符等效于分别分配类成员:

pair<first,second> &operator=(const pair<first, second> &other)
{
   first=other.first;
   second=other.second;
   return *this;
}

这是默认赋值运算符的大致示例。

但是您不能在这里修改first类成员,因为它是const类成员。因此,默认分配运算符被删除。最终结果:无法将具有std::pair值的const分配给另一个这样的对。

您现在应该可以自己弄清楚为什么配对向量上的insert()不起作用。

insert()大致等效于在插入点之后的向量中将所有现有值平移一个,以便为新值腾出空间。换句话说:

 value[n+1]=values[n];

对于超过插入点的所有值(我暂时忽略了将向量增长一个值的工作,这与本次讨论无关)。

但是,正如我所解释的,默认的赋值运算符已删除,因为value具有一个const类成员。

push_back之所以有效,是因为不需要插入任何内容,只需在向量的末尾添加一个新值即可。如果需要重新分配向量以适应其增长,则使用复制或移动构造函数,这些构造函数对于具有std::pair值的const仍然有效。

答案 1 :(得分:3)

由于数据类型const的{​​{1}}性质(它有一个kv成员const),它的复制分配运算符已被隐式删除。编译器。

具体来说,您正在使用的first的重载要求数据类型(std::vector::insert)为 CopyAssignable (可以以kv的形式复制)。您的const成员禁止这样做。

另一方面,a = b要求类型为 CopyInsertable (可以是复制构造的),您的类型符合

因此,std::vector::push_back将不起作用,但insert将起作用。最简单的解决方法是让push_back的第一个成员失去const。如果您不希望有人修改键/值,请不要让他们修改。返回键/值元组时,应将其用作const指针或引用。