I don't understand why the padding after m_data
, when the copy constructor constructs the object, is not initialized to 0 in an optimized build like -O2
. The default constructor always seems to initialize it. I haven't tried yet other special member functions.
Is this behaviour implementation-defined? Not defined?
Is there a way to initialize it?
Thanks
#include <climits>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <limits>
#include <span>
void print(std::span<const std::byte> const span)
{
for (auto const i : span) {
std::cout << std::to_integer<int>(i) << ' ';
}
std::cout << '\n';
}
struct Foo {
Foo()
{}
Foo(const Foo&)
{}
/*alignas(1)*/ std::byte m_data[1] = {};
uint32_t val = INT_MAX;
};
inline auto objAsBytes(const auto& obj)
{
return std::as_bytes(std::span { std::addressof(obj), 1 });
}
int main()
{
auto foo = Foo {};
std::span fooAsBytes = objAsBytes(foo);
std::cout << "fooAsBytes\n";
print(fooAsBytes);
auto fooCopy = foo;
std::span fooCopyBytes = objAsBytes(fooCopy);
std::cout << "fooCopyBytes\n";
print(fooCopyBytes);
Foo fooAssign;
fooAssign = foo;
std::span fooAssignBytes = objAsBytes(fooAssign);
std::cout << "fooAssignBytes\n";
print(fooAssignBytes);
}
After more research today, I found a good explanation.
First, I found a good related question, Does C++ standard guarantee the initialization of padding bytes to zero for non-static aggregate objects?
It first mentions cppreference zero-initialization,
c++ standard dcl.init.general#6 which states this:
if T is a (possibly cv-qualified) non-union class type, its padding bits ([basic.types.general]) are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;
The question also mentions differences between GCC and Clang regarding zero-initialization. It is not my question but good to mention.
The reason zero-initialization is not happening is a mix of having user-defined default and copy constructors and default member initializers instead of value initialization.