Есть ли способ заставить C ++ struct value инициализировать все переменные-члены POD? - PullRequest
7 голосов
/ 14 октября 2010

Предположим, у меня есть структура C ++, которая имеет переменные-члены 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 без явного добавления их инициализации в этом случае?

Ответы [ 3 ]

10 голосов
/ 14 октября 2010

Самый простой способ - написать класс автоинициализированных шаблонов initialized<T>:

РЕДАКТИРОВАТЬ: теперь я понимаю, что это может быть сделано еще более гибким, позволяя вам объявить 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 и т. Д. Но вы поняли идею.

10 голосов
/ 14 октября 2010

Связанный вопрос здесь

Есть ли способ обеспечить инициализацию значения всех переменных-членов POD без явного добавления их инициализации в этом случае?

Я не уверен, возможно ли что-то подобное [напрямую] или нет, но следующие работы

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 ~ $ 
0 голосов
/ 14 октября 2010

Вы можете добавить базовую структуру:

struct PODStruct
{
  PODStruct(unsinged int count) { memset( this, 0, count);}
};

А затем ваша структура получена из этой базовой структуры, в первую очередь, если у вас более одной базовой структуры,

struct Struct : PODStruct
{
  Struct();
  std::string Str;
  int Int;
}

Struc::Struct() : PODStruct(sizeof(Struct))
{
}
...