Is it possible to defer member initialization to the constructor body?

后端 未结 8 606
一生所求
一生所求 2021-01-13 14:25

I have a class with an object as a member which doesn\'t have a default constructor. I\'d like to initialize this member in the constructor, but it seems that in C++ I can\'

8条回答
  •  别那么骄傲
    2021-01-13 14:55

    This is a really ancient thread, but there is another possibility using an anonymous union. Let me first declare a helper class without a standard constructor, which will inform us about the moment of constructor and destructor calling:

    #include 
    #include 
    
    struct Embedded
    {
        Embedded(const char* init_name)
        : name(init_name)
        {
            std::cout << "Constructor of Embedded: " << name << std::endl;
        }
    
        ~Embedded()
        {
            std::cout << "Destructor of Embedded: " << name << std::endl;
        }
    
        std::string name;
    };
    

    Now let us embed three different objects of this class in another class. One is placed inside a union (which won't be automatically initialized). For this object, constructor and destructor must be manually called (using placement new). This is possible at any position in the code.

    struct Demo
    {
        Embedded object_1 {"object_1"};
        Embedded object_2;
    
        union   // members won't be automatically constructed
        {
            Embedded object_3;  // don't use standard initializer (as for object_1)
        };
    
        Demo()
        : object_2("object_2")
        {
            std::cout << "Constructor of Demo" << std::endl;
            new (&object_3) Embedded ("object_3");
        }
    
        ~Demo()
        {
            object_3.~Embedded();
            std::cout << "Destructor of Demo" << std::endl;
        }
    };
    

    Finally, use the Demo class in its own scope:

    int main()
    {
        std::cout << "main() start" << std::endl;
    
        {
            Demo demo;
            std::cout << "demo created" << std::endl;
        }
    
        std::cout << "main() end" << std::endl;
        return 0;
    }
    

    As you can see from the output, the constructor is deferred.

    main() start
    Constructor of Embedded: object_1
    Constructor of Embedded: object_2
    Constructor of Demo
    Constructor of Embedded: object_3
    demo created
    Destructor of Embedded: object_3
    Destructor of Demo
    Destructor of Embedded: object_2
    Destructor of Embedded: object_1
    main() end
    

    So you can exactly define the moment of the deferred constructor call. The downside is, that you also have to manually call the destructor or really bad things can happen.

提交回复
热议问题