Is it valid to copy a struct some of whose members are not initialized?
I suspect it is undefined behavior, but if so, it makes leaving any uninitialized members in a struct (even if those members are never used directly) quite dangerous. So I wonder if there is something in the standard that allows it.
For instance, is this valid?
struct Data {
int a, b;
};
int main() {
Data data;
data.a = 5;
Data data2 = data;
}
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 union
s, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With