Suppose I have a C++ struct that has both POD and non-POD member variables:
struct Struct {
std::string String;
int Int;
};
and in order for my program to produce reproduceable behavior I want to have all member variables initialized at construction. I can use an initializer list for that:
Struct::Struct() : Int() {}
the problem is as soon as I need to change my struct and add a new POD member variable(say bool Bool
) I risk forgetting to add it to the initializer list. Then the new member variable will not be value-initialized during 开发者_开发百科struct construction.
Also I can't use the memset()
trick:
Struct::Struct()
{
memset( this, 0, sizeof( *this ) ); //can break non-POD member variables
}
because calling memset()
to overwrite already constructed non-POD member variables can break those.
Is there a way to enforce value-initialization of all POD member variables without explicitly adding their initialization in this case?
The cleanest way would be to write the auto-initialzed template class initialized<T>
:
EDIT: I realize now it can be made even more flexible by allowing you to declare initialized<Struct>
. This means that you can declare initialization without modifying the original Struct
. The default initialization 'T()' was inspired on Prasoons answer.
template<class T>
struct initialized
{
public:
initialized()
{ value = T(); }
initialized(T t)
{ value = t; }
initialized(const initialized<T>& x)
{ value = x.value; }
T* operator &() { return &value; }
operator T&() { return value; }
private:
T value;
};
struct PodStruct
{
std::string String;
int Int;
};
struct GlorifiedPodStruct
{
std::string String;
initialized<int> Int;
};
void Test()
{
GlorifiedPodStruct s;
s.Int = 1;
int b = s.Int;
int * pointer = &s.Int;
initialized<PodStruct> s2;
}
This compiles, but may need more conversion operators, handling of keywords like volatile, etc. But you get the idea.
Linked Question here
Is there a way to enforce value-initialization of all POD member variables without explicitly adding their initialization in this case?
I am not sure whether something like that is possible [directly] or not but the following works
prasoon@prasoon-desktop ~ $ cat check.cpp && clang++ check.cpp && ./a.out
#include <iostream>
struct Struct {
std::string String;
int Int;
bool k;
// add add add
};
struct InStruct:Struct
{
InStruct():Struct(){}
};
int main()
{
InStruct i;
std::cout<< i.k << " " << i.Int << std::endl;
}
0 0
prasoon@prasoon-desktop ~ $
You can add a base struct:
struct PODStruct
{
PODStruct(unsinged int count) { memset( this, 0, count);}
};
And then your struct derived from this base struct, first place if you have more than one base structs,
struct Struct : PODStruct
{
Struct();
std::string Str;
int Int;
}
Struc::Struct() : PODStruct(sizeof(Struct))
{
}
精彩评论