Why does std::set seem to force the use of a const

2019-02-21 07:20发布

Consider the simple program below, which attempts to iterate through the values of a set using NON-const references to the elements in it:

#include <set>
#include <iostream>

class Int
{
public:
   Int(int value) : value_(value) {}
   int value() const { return value_; }
   bool operator<(const Int& other) const { return value_ < other.value(); }
private:
   int value_;
};

int
main(int argc, char** argv) {
   std::set<Int> ints;
   ints.insert(10);
   for (Int& i : ints) {
      std::cout << i.value() << std::endl;
   }
   return 0;
}

When compiling this, I get an error from gcc:

test.c: In function ‘int main(int, char**)’:
test.c:18:18: error: invalid initialization of reference of type ‘Int&’ from expression of type ‘const Int’  
for (Int& i : ints) {  
              ^  

Yes, I know I'm not actually trying to modify the elements in the for loop. But the point is that I should be able to get a non-const reference to use inside the loop, since the set itself is not const qualified. I get the same error if I create a setter function and use that in the loop.

标签: c++ c++11 stdset
4条回答
We Are One
2楼-- · 2019-02-21 07:30

A set is like a map with no values, only keys. Since those keys are used for a tree that accelerates operations on the set, they cannot change. Thus all elements must be const to keep the constraints of the underlying tree from being broken.

查看更多
倾城 Initia
3楼-- · 2019-02-21 07:31

From the cpp reference:

In a set, the value of an element also identifies it (the value is itself the key, of type T), and each value must be unique. The value of the elements in a set cannot be modified once in the container (the elements are always const), but they can be inserted or removed from the container.

查看更多
Root(大扎)
4楼-- · 2019-02-21 07:46

std::set uses the contained values to form a fast data structure (usually, a red-black tree). Changing a value means the whole structure needs to be altered. So, forcing constness, std::set prevents you from pushing it into a non-usable state.

查看更多
Evening l夕情丶
5楼-- · 2019-02-21 07:52

The behaviour is by design.

Giving you a non-const iterator could inspire you to change the element in the set; the subsequent iterating behaviour would then be undefined.

Note that the C++ standard says that set<T>::iterator is const so the old-fashioned pre C++11 way still wouldn't work.

查看更多
登录 后发表回答