max
max

Reputation: 52273

Reference member initialized from a by-value constructor parameter

Under what conditions is this code correct:

struct A {
  A(B b) : b_(b) {}
 private:
  const B& b_;
}
B b_permanent;
A a(b_permanent);

IIUC, b will be a copy of b_permanent, and b_ will be bound to that copy. But what is the lifetime of b? If it is only for the duration of the ctor, then this is wrong because b_ will be bound to an out-of-scope object by the time ctor finishes. And if that's the case, why is it even legal in C++, and doesn't even cause lint warnings?

OTOH, if b lifetime is extended to equal the lifetime of a, then can you link me to a rule that states that?

Does the answer depend on whether B is a fundamental or compound type?

Does the answer depend on C++ 11 vs 14 vs 17? (I'm not interested in anything before 11.)

Upvotes: 0

Views: 57

Answers (1)

Brian Bi
Brian Bi

Reputation: 119219

The non-static member b_ has the lifetime of the enclosing object. The object b has automatic storage duration since it's a function parameter, and it is destroyed when the constructor returns. So indeed b_ becomes a dangling reference at that point.

It is legal to write code like this because detecting such code is a quality-of-implementation issue. Although in this case it's obvious that the code is wrong, reference-binding can involve more complicated logic to determine which object the reference is being bound to. It's impossible for the compiler to detect in all cases that this is occurring. If you want your toolchain to be able to catch easy cases like this one, file a feature request.

Upvotes: 5

Related Questions