简体   繁体   中英

const_cast const STL container, is it undefined behavior?

I know that use of const_cast won't introduce undefined behaviour (ie, it's safe to use), as long as the variable you're const_cast ing wasn't originally defined as const or if it was originally defined as const you're not modifying it via its const_cast ed alias.

However, It is also known that most STL containers (eg, std::vector , std::set ), allocate their internal buffers dynamically. Based on this fact I think that is impossible for a const defined std::vector to be placed in read-only memory.

Naturally, if the above holds I come to the assumption that such kind of STL containers even if they're defined as const , eg,:

std::vector<int> const v;

const_cast ing them and altering them via their const_cast ed alias is legitimate and won't cause any undefined behavior.

Does the above assumption holds or I'm wrong?

The C++ standard explicitly points out that casting away const for an object created via new const T , and modifying it, is Undefined Behavior.

Eg, the C++11 standard contains this example in its §7.1.6.1/4:

 const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object 

Examples in the standard are non-normative, just examples, and can be wrong. For example, in C++03 nearly all examples that used <iostream> were wrong (at that time it was formally necessary to also include <ostream> , but that was not the intention of the committee), and the expression examples in C++03 §5/4 were wrong, saying the behavior was unspecified rather than undefined (which might have reflected an original intention). However, the above example is correct.

This shows that dynamically allocated memory needs not be mutable: that modifying it, can have Undefined Behavior.

However, when eg a std::string is created, its allocation of a buffer (if any) occurs during execution of a constructor, at which point the object is not yet const , and the buffer is not allocated as const . So the buffer, if one is allocated, is not originally const . But regarding this particular example the std::string may use the small buffer optimization where it uses storage directly in the object, which would then be originally const (potentially allocated in read only memory). And this goes to the rational for the rule that no originally const object can be modified.


In addition to the read-only memory scenario, the rationale for UB includes that it can give compilers optimization possibilities.

As juanchopanza notes in a comment to the question ,

Optimizers use this to do all kind of crazy stuff that assumes const objects won't be modified.

Breaking the assumptions of the optimizer by modifying an originally const object, can have disastrous and effectively unpredictable consequences.

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