简体   繁体   中英

Is it UB to change a member of a const object via a constructor-bound reference?

In short: Does the following code have Undefined Behavior, or is this fine?

struct X
{
  X(int b)
    : value(b)
    , ref(value)
  {
  }

  int value;
  int& ref;

  void isThisUB() const
  {
    ref = 1;
  }
};

int main()
{
  const X x(2);
  // Is either of these fine?
  x.isThisUB();
  x.ref = 3;
  return x.value;
}

https://godbolt.org/z/1TE9a7M4a

X::value is const for x . According to my understanding of const semantics, this means that modifying it in any way is UB. Yet we can take a non-const reference to it in the constructor and then modify it through that, either in a const member function or directly.

The C++ (at least 17) standard gives an example of const-related UB in [dcl.type.cv] that looks mostly the same, except it employs const_cast . Note how p->xj = 99 is denoted as UB. I do not see a fundamental difference between achieving this with const_cast vs my above code.

So, is the code above UB? Are non-const reference members/pointers really this big of a footgun?

(If you can come up with search keywords that yield a related question and not just random const stuff, I'll be mighty impressed.)

Does the following code have Undefined Behavior, or is this fine?

It has UB. Standard says:

[dcl.type.cv]

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior .

x is const and you modify its non-mutable member.

I do not see a fundamental difference between achieving this with const_cast vs my above code.

Indeed. Both are UB for the same reason.

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