Я недавно наткнулся на следующую "лазейку" вокруг const-correctness:
struct Inner {
int field = 0;
void Modify() {
field++;
}
};
struct Outer {
Inner inner;
};
class MyClass {
public:
Outer outer;
Inner& inner; // refers to outer.inner, for convenience
MyClass() : inner(outer.inner) {}
void ConstMethod() const {
inner.Modify(); // oops; compiles
}
};
Кроме того, представляется возможным использовать эту лазейку для изменения объекта, объявленного как const
, который, как я считаю, является неопределенным поведением:
int main() {
const MyClass myclass;
std::cout << myclass.outer.inner.field << "\n"; // prints 0
myclass.ConstMethod();
std::cout << myclass.outer.inner.field << "\n"; // prints 1
}
Это пугает меня, потому что кажется, что я только что вызвал неопределенное поведение, связанное с const-correctness в программе, которая не использует const_cast
или отбрасывает константу, используя C-стиль.
Итак, мои вопросы:
- Правильно ли я говорю, что вышеупомянутая программа имеет неопределенное поведение?
- Если это так, это ошибка языка? Есть ли строка в вышеупомянутой программе, которая, возможно, не должна (может быть разумно сделана) не компилироваться?
- Существуют ли какие-то рекомендации, которые следует соблюдать, чтобы избежать этой категории неопределенного поведения на практике?