Copying structs with uninitialized members

Yes, if the uninitialized member is not an unsigned narrow character type or std::byte, then copying a struct containing this indeterminate value with the implicitly defined copy constructor is technically undefined behavior, as it is for copying a variable with indeterminate value of the same type, because of [dcl.init]/12.

This applies here, because the implicitly generated copy constructor is, except for unions, defined to copy each member individually as if by direct-initialization, see [class.copy.ctor]/4.

This is also subject of the active CWG issue 2264.

I suppose in practice you will not have any problem with that, though.

If you want to be 100% sure, using std::memcpy always has well-defined behavior if the type is trivially copyable, even if members have indeterminate value.


These issues aside, you should always initialize your class members properly with a specified value at construction anyway, assuming you don't require the class to have a trivial default constructor. You can do so easily using the default member initializer syntax to e.g. value-initialize the members:

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

int main() {
  Data data;
  data.a = 5;
  Data data2 = data;
}

In general, copying uninitialized data is undefined behavior because that data may be in a trapping state. Quoting this page:

If an object representation does not represent any value of the object type, it is known as trap representation. Accessing a trap representation in any way other than reading it through an lvalue expression of character type is undefined behavior.

Signalling NaNs are possible for floating point types, and on some platforms integers may have trap representations.

However, for trivially copyable types it is possible to use memcpy to copy the raw representation of the object. Doing so is safe since the value of the object is not interpreted, and instead the raw byte sequence of the object representation is copied.