简体   繁体   中英

Const-Correctness for Elements of std Containers

The following is bad:

vector<const int> vec;

The problem is that the template type needs to be assignable. The following code compiles [EDIT: in Visual Studio 2010], demonstrating a problem with the above:

vector<const int> vec;
vec.push_back(6);
vec[0] += 4;

With more complicated types, this can be a serious problem.

My first question is whether there is a reason for this behavior. It seems to me like it might be possible to make const containers that disallow the above and non-const containers that allow it.

Second, is there a way to make containers that function in this way?

Third, what is actually happening here (with a user type)? I realize it is undefined behavior, but how is the STL even compiling this at all?

The reason std::vector<T const> isn't allowed is that the object in a vector may need to be reshuffled when inserting at a different place than the beginning. Now, the member std::vector<T>::push_back(T const& v) is conceptually equivalent to (leaving the allocator template parameter out as it is irrelevant for this discussion)

template <typename T>
void std::vector<T>::push_back(T const& v) {
    this->insert(this->end(), v);
}

which seems to be how it is implemented on some implementations. Now, this operation would requires, in general, that some objects might need to be moved and, thus, the T argument needs to be assignable. It seems that the standard library shipping with MSVC++ doesn't delegate the operation but does all the necessary handling, ie, resizing the array and moving the objects appropriately when running out of space, in push_back() . It isn't quite clear what the requirements are on the type T to be able to use push_back() .

In principle, a container supporting both T const and an insert() operation in the middle would be possible, though: Nothing requires the internal storage to be T rather than typename std::remove_const<T>::type while exposing a T& in the interface. It is necessary to be a bit careful about the const -version ofoperations like operator[]() because just using T const& as the return type when T is some type S const would result in a type S const const . In C++ 2003 this would be an error, in C++ 2011 I think the const are just collapsed. To be safe you could use typename std::add_const<T>::type& .

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