Есть ли способ сделать значение С++ struct-initialize всеми переменными-членами POD?
Предположим, что у меня есть структура С++, которая имеет как переменные-члены POD, так и не-POD:
struct Struct {
std::string String;
int Int;
};
и для того, чтобы моя программа создавала воспроизводимое поведение, я хочу, чтобы все переменные-члены были инициализированы при построении. Для этого я могу использовать список инициализаторов:
Struct::Struct() : Int() {}
проблема возникает, как только мне нужно изменить мою структуру и добавить новую переменную-член POD (скажем bool Bool
). Я рискую забыть добавить ее в список инициализаторов. Тогда новая переменная-член не будет инициализирована значением при построении структуры.
Также я не могу использовать трюк memset()
:
Struct::Struct()
{
memset( this, 0, sizeof( *this ) ); //can break non-POD member variables
}
потому что вызов memset()
для перезаписывания уже построенных не-POD-переменных-членов может нарушить их.
Есть ли способ принудительно инициализировать значение всех переменных-членов POD без явного добавления их инициализации в этом случае?
Ответы
Ответ 1
Самый чистый способ - записать класс автоинициализированных шаблонов initialized<T>
:
EDIT: теперь я понимаю, что его можно сделать еще более гибким, разрешив вам объявить initialized<Struct>
. Это означает, что вы можете объявить инициализацию без изменения оригинала Struct
. Инициализация по умолчанию "T()" была вдохновлена ответом Prasoons.
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;
}
Это компиляция, но может потребоваться больше операторов преобразования, обработка ключевых слов, таких как volatile и т.д. Но вы получаете идею.
Ответ 2
Связанный вопрос здесь
Есть ли способ принудительно инициализировать значение всех переменных-членов POD без явного добавления их инициализации в этом случае?
Я не уверен, возможно ли что-то подобное [прямо] или нет, но следующие работы
[email protected] ~ $ 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
[email protected] ~ $
Ответ 3
Вы можете добавить базовую структуру:
struct PODStruct
{
PODStruct(unsinged int count) { memset( this, 0, count);}
};
И затем ваша структура, полученная из этой базовой структуры, на первом месте, если у вас есть несколько базовых структур,
struct Struct : PODStruct
{
Struct();
std::string Str;
int Int;
}
Struc::Struct() : PODStruct(sizeof(Struct))
{
}