在构造之前引用变量是否定义良好

cig*_*ien 8 c++ language-lawyer

这在本质上类似的问题,这是提出和回答的c。那里的评论暗示,c++对于c++.

以下程序是否定义明确?

int f(int& b) 
{ 
  b = 42; 
  return b; 
}

int a { f(a) };
Run Code Online (Sandbox Code Playgroud)

对我来说似乎没问题,但另一方面,如何a从一个函数计算的值构造它,它本身会修改a?我对此有一种先有鸡还是先有蛋的感觉,所以解释一下会很好。就其价值而言,它似乎有效。

这似乎是同一个问题,所以这里是;对于类类型和基本类型,答案是否会有所不同。即以下格式是否正确?

struct S { int i; };

S f(S& b) 
{ 
    b.i = 42; 
    return b; 
}

S a { f(a) };
Run Code Online (Sandbox Code Playgroud)

同样,就其价值而言,这似乎也有效。

Bri*_*ian 6

该行为在 C++20 中似乎未定义。该更改由P1358 进行,解决了 CWG 2256。由于缺陷解决方案通常具有追溯性,因此该代码在所有 C++ 版本中都应被视为 UB。

根据[basic.life]/1

... 类型对象的生命周期T开始于:

  • 获得具有正确对齐和类型大小的存储T,并且
  • 其初始化(如果有)已完成(包括空初始化)...

f(a)被调用时,对象a还没有开始它的生命周期,因为它的初始化还没有完成。根据[basic.life]/7

类似地,在对象的生命周期开始之前但在对象将占用的存储空间已分配之后……可以使用引用原始对象的任何泛左值,但只能以有限的方式使用。...程序有未定义的行为,如果:

  • 泛左值用于访问对象...

因此,a在其初始化完成之前写入是 UB,即使已经分配了存储。