Is this C++ structure initialization trick safe?

前端 未结 16 1155
有刺的猬
有刺的猬 2020-12-23 17:56

Instead of having to remember to initialize a simple \'C\' structure, I might derive from it and zero it in the constructor like this:

struct MY_STRUCT
{
            


        
16条回答
  •  [愿得一人]
    2020-12-23 18:31

    PREAMBLE:

    While my answer is still Ok, I find litb's answer quite superior to mine because:

    1. It teaches me a trick that I did not know (litb's answers usually have this effect, but this is the first time I write it down)
    2. It answers exactly the question (that is, initializing the original struct's part to zero)

    So please, consider litb's answer before mine. In fact, I suggest the question's author to consider litb's answer as the right one.

    Original answer

    Putting a true object (i.e. std::string) etc. inside will break, because the true object will be initialized before the memset, and then, overwritten by zeroes.

    Using the initialization list doesn't work for g++ (I'm surprised...). Initialize it instead in the CMyStruct constructor body. It will be C++ friendly:

    class CMyStruct : public MY_STRUCT
    {
    public:
        CMyStruct() { n1 = 0 ; n2 = 0 ; }
    };
    

    P.S.: I assumed you did have no control over MY_STRUCT, of course. With control, you would have added the constructor directly inside MY_STRUCT and forgotten about inheritance. Note that you can add non-virtual methods to a C-like struct, and still have it behave as a struct.

    EDIT: Added missing parenthesis, after Lou Franco's comment. Thanks!

    EDIT 2 : I tried the code on g++, and for some reason, using the initialization list does not work. I corrected the code using the body constructor. The solution is still valid, though.

    Please reevaluate my post, as the original code was changed (see changelog for more info).

    EDIT 3 : After reading Rob's comment, I guess he has a point worthy of discussion: "Agreed, but this could be an enormous Win32 structure which may change with a new SDK, so a memset is future proof."

    I disagree: Knowing Microsoft, it won't change because of their need for perfect backward compatibility. They will create instead an extended MY_STRUCTEx struct with the same initial layout as MY_STRUCT, with additionnal members at the end, and recognizable through a "size" member variable like the struct used for a RegisterWindow, IIRC.

    So the only valid point remaining from Rob's comment is the "enormous" struct. In this case, perhaps a memset is more convenient, but you will have to make MY_STRUCT a variable member of CMyStruct instead of inheriting from it.

    I see another hack, but I guess this would break because of possible struct alignment problem.

    EDIT 4: Please take a look at Frank Krueger's solution. I can't promise it's portable (I guess it is), but it is still interesting from a technical viewpoint because it shows one case where, in C++, the "this" pointer "address" moves from its base class to its inherited class.

提交回复
热议问题