复制具有未初始化成员的结构

Tom*_*jka 31 c++ initialization copy-constructor undefined-behavior

复制其中一些成员未初始化的结构是否有效?

我怀疑这是未定义的行为,但如果是这样,则将任何未初始化的成员留在结构中(即使这些成员从未直接使用)非常危险。所以我想知道标准中是否有某些内容允许这样做。

例如,这有效吗?

struct Data {
  int a, b;
};

int main() {
  Data data;
  data.a = 5;
  Data data2 = data;
}
Run Code Online (Sandbox Code Playgroud)

wal*_*nut 25

是的,如果未初始化的成员不是无符号窄字符类型或std::byte,则使用隐式定义的复制构造函数复制包含此不确定值的结构在技术上是未定义的行为,因为它是复制具有相同类型的不确定值的变量,因为[ dcl.init]/12

这适用于此处,因为隐式生成的复制构造函数(s 除外)union被定义为单独复制每个成员,就像通过直接初始化一样,请参阅[class.copy.ctor]/4

这也是当前CWG 问题 2264的主题。

不过,我想在实践中你不会有任何问题。

如果您想 100% 确定,那么std::memcpy如果类型是可简单复制的,则使用总是具有明确定义的行为,即使成员具有不确定的值。


抛开这些问题不谈,假设您不要求类有一个简单的默认构造函数,您应该始终在构造时使用指定的值正确初始化类成员。您可以使用默认成员初始化语法轻松地完成此操作,例如对成员进行值初始化:

struct Data {
  int a{}, b{};
};

int main() {
  Data data;
  data.a = 5;
  Data data2 = data;
}
Run Code Online (Sandbox Code Playgroud)


And*_*hev 13

一般来说,复制未初始化的数据是未定义的行为,因为该数据可能处于捕获状态。引用页:

如果对象表示不表示对象类型的任何值,则称为陷阱表示。除了通过字符类型的左值表达式读取陷阱表示之外,以任何方式访问陷阱表示都是未定义的行为。

对于浮点类型,信号 NaN 是可能的,并且在某些平台上,整数可能具有陷阱表示。

然而,对于普通可复制类型,可以用来memcpy复制对象的原始表示。这样做是安全的,因为不会解释对象的值,而是复制对象表示的原始字节序列。