В вашем примере нет неопределенного поведения.
Приведенный выше код не вызывает неопределенное поведение, поскольку базовые данные (int) являются изменяемыми.Давайте посмотрим на более простой пример.
#include <iostream>
struct IntPtr {
int* data;
};
int main() {
int a = 0;
const IntPtr p { &a };
*p.data = 10;
std::cout << a; // Prints 10
}
Все это совершенно законно, потому что IntPtr
const приводит к тому, что data
является постоянным указателем на int, а НЕ указателем на константу int.Мы можем изменить данные, на которые указывает p.data
;мы просто не можем изменить p.data
.
const IntPtr p { &a };
*p.data = 10; // This is legal
int b;
p.data = &b; // This is illegal (can't modify const member)
Итак, как этот пример применим к std::vector
? Давайте добавим возможность индексации в IntPtr
:
class IntPtr {
int* data;
public:
IntPtr() = default;
IntPtr(int size) : data(new int[size]) {}
// Even though this is a const function we can return a mutable reference
// because the stuff data points to is still mutable.
int& operator[](int index) const {
return data[index];
}
};
int main() {
const IntPtr i(100);
i[1] = 10; // This is fine
};
Даже еслиIntPtr
является константой, базовые данные являются изменяемыми , потому что они создаются путем выделения массива изменяемых целых чисел.То же самое для std::vector
: лежащие в основе данные все еще являются изменяемыми, поэтому безопасно const_cast
их хранить.