【发布时间】:2018-12-29 02:27:37
【问题描述】:
我最近偶然发现了以下关于 const 正确性的“漏洞”:
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_cast 或使用 C 风格强制转换的程序中调用了与 const 正确性相关的未定义行为。
所以,我的问题是:
- 我是否正确地说上述程序具有未定义的行为?
- 如果是这样,这是一个语言错误吗?上述程序中是否有一行可以说不应该(可以合理地不编译)?
- 在实践中是否应遵循一些准则以避免此类未定义的行为?
【问题讨论】:
-
如果您打开警告,您对此有任何了解吗?我实际上并不认为这是未定义的,只是不可取的。
-
它基于一个简单的事实,即在构造函数和析构函数内部,
const对象始终被视为非常量对象。是的,您可以使用它来解决 const 正确性规则而无需强制转换。 -
不是答案,而是可以帮助防止这种情况发生的事情:en.cppreference.com/w/cpp/experimental/propagate_const
-
正如我在下面提到的,相关问题是
myclass.inner是否“首次创建”为const。不是MyClass定义中的const,所以我真的不知道!
标签: c++ class reference constants