简体   繁体   中英

C++ std::vector<std::pair<const int, int>> can not insert element

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

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

I tried to insert element into that vector, but the compiler gives this eerror:

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

while push_back() will compile correctly.Why is that? And what's the correct way to insert element into such vector?

ADD: The reason why I use std::pair<const int, int> is that I want to implement something like std::map , and the key in the key-value pair should not be modified. But I'm not sure if std::pair<const int, int> is the correct approach to do this.

Let's start by observing the following:

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

a=b;

This will not compile either. Why? Because you are in effect declaring the following class:

class my_pair {

public:
    // ... Bunch of irrelevant stuff

    const int first;
    int second;
};

This class has its default assignment operator deleted. The default assignment operator is equivalent to assigning class members individually:

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

This is a rough example of what a default assignment operator looks like.

But you can't modify the first class member, here, because it is a const class member. Hence, the default assignment operator is deleted. End result: cannot assign a std::pair with a const value to another such pair.

You should now be able to figure out by yourself why insert() on your vector of pairs doesn't work.

insert () is, roughly, equivalent to shifting over all existing values by one, in the vector, after the insertion point, to make room for the new value. In other words:

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

For all values past the insertion point (I'm ignoring for the moment the work done to grow the vector by one value, which is irrelevant to this discussion).

But the default assignment operator, as I explained, is deleted because the value has a const class member.

push_back works because nothing needs to be inserted, only a new value needs to be added to the end of the vector. If the vector needs to be reallocated, to accomodate its growth, that uses copy or move constructors, which are still valid for a std::pair with a const value.

Due to the const nature of the your data type kv (it has a const member first ), it's copy-assignment operator has been implicitly deleted by the compiler.

Specifically, the overload of std::vector::insert you're using requires the data type ( kv ) be CopyAssignable (can be copied with a form of a = b ). Your const member prohibits that.

On the other hand, std::vector::push_back requires the type be CopyInsertable (it can be copy-constructed), which your type is compliant with.

Therefore, insert will not work, but push_back will. The easiest fix is to lose the const from the kv first member. If you don't want someone to modify a key/value, then don't let them. When returning key/value tuples do so as const pointers or references.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM