引用类型的数据成员提供围绕const正确性的"漏洞"

HC4*_*ica 19 c++ reference class constants

我最近偶然发现了以下关于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
  }
};
Run Code Online (Sandbox Code Playgroud)

它似乎有可能使用这个漏洞来修改声明为的对象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
}
Run Code Online (Sandbox Code Playgroud)

这让我很害怕,因为我似乎只是调用了一个与const-correctness相关的未定义行为,这个行为不使用const_cast或使用C风格的强制转换去掉constness .

所以,我的问题是:

  • 我是否正确地说上述程序有未定义的行为?
  • 如果是这样,这是一个语言错误吗?上述程序中是否有一行可以说是不应该(可以合理地不编译)编译?
  • 在实践中是否应该遵循一些指导原则来避免这种类型的未定义行为?

Pas*_* By 5

const对象的任何修改都是未定义的行为,而片段确实这样做.

该程序不是格式错误(这将需要编译错误),因为在初始化时inner,cv限定符尚未生效.

从编译器的角度来看,要发出警告,需要它分析导致inner.Modify()并证明inner 必须引用const对象的所有代码路径,这在一般情况下是不可能的.

最好的建议可能没有内部指针/引用,无论如何都是邪恶的.

  • @JoshuaGreen一个子对象显然是对象的一部分,否则你将能够用一个类做任何你想做的事情.阅读[this](https://timsong-cpp.github.io/cppwp/dcl.type.cv#4)和[this](https://timsong-cpp.github.io/cppwp/basic.type.限定词#1.1)如果你仍然不相信. (2认同)