I know a POD class can safely be memset. In c++17(?) std::is_pod is being replaced by std::is_standard_layout and std::is_trivial. Can a non trivial but standard layout struct be safely memset IF it only contains char[] data and a user defined constructor.
Legacy class that has dozens of char[] member variables.
#include <cstring>
#include <memory>
#include <iostream>
#include <type_traits>
struct A
{
// dozens of fields all char[] which need to initialized to '0'
char foo[10]; // example char[] field
// dozens of other fields all char[] which need to be initialized to non '0'
struct AA
{
char bar[10];
// dozens of other fields
} sub[7];
};
// What I want to turn struct A into
struct B
{
B()
{
// My question: Is this permissible?
std::memset(this, '0', sizeof(*this));
// Initialize all the other member variables that need different values
std::memset(foo, ' ', sizeof(foo));
}
// dozens of fields all char[] which need to initialized to '0'
char foo[10]; // example char[] field
// dozens of other fields all char[] which need to be initialized to other values in constructor
struct BB
{
char bar[10];
// dozens of other fields
} sub[7];
};
int main(int argc, char* argv[])
{
bool isTrivialA = std::is_trivial<A>::value;
bool isStandardLayoutA = std::is_standard_layout<A>::value;
bool isTrivialCopyA = std::is_trivially_copyable<A>::value;
std::cout << "Is A trivial: " << isTrivialA << std::endl;
std::cout << "Is A standard layout: " << isStandardLayoutA << std::endl;;
std::cout << "Is A trivial copy: " << isTrivialCopyA << std::endl << std::endl;
bool isTrivialB = std::is_trivial<B>::value;
bool isStandardLayoutB = std::is_standard_layout<B>::value;
bool isTrivialCopyB = std::is_trivially_copyable<B>::value;
std::cout << "Is B trivial: " << isTrivialB << std::endl;
std::cout << "Is B standard layout: " << isStandardLayoutB << std::endl;
std::cout << "Is B trivial copy: " << isTrivialCopyB << std::endl;
}
Existing code just does a memset on the object when it's used.
A legacy;
memset(&legacy, '0', sizeof(legacy));
I would like call the user defined constructor on the updated struct B because there are dozens of fields which actually need to be initialized to different values besides '0'. I know I could have a non member function to initialize the values but that seems clunky.
B newer; // Call user defined constructor
Is the constructor defined in B with memset() of the 'this' pointer safe / allowed?
{}
initializer after every field to zero them by default. (It's not even necessary for fields in nested structs.) – HolyBlackCatchar foo[10] = {};
andsub[7] = {};
in the struct declaration, and now everything interesting is 0 initialized. (The "not interesting" parts would be if there was any padding, which in thestruct A
example there isn't on my platform.) – Eljay