Search code examples
c++socketsconstructordefault-constructorlazy-initialization

How to do lazy construct in C++?


I want to make 'lazy construct' in a C++ class, a simple method to do that is something like this:

#include "b.hpp" // class B

class A {

public:
  // invoke B() in b.hpp, this constructor do not actually do init      
  A(int v_in) : v(v_in) {} 

  void foo() {
    if(flag == false) {
      b = create_B_obj();
      flag = true;
    }
  }
private:
  B create_B_obj() {
    // some expensive ops
    //...
  }

private:
  bool flag = false;
  B b;
  int v;
};

But a existing problem is that B may not contain a default constructor (B()), so how can I do 'lazy construct' in this case?

BTW: class B in my project is something like a socket which need to do connect or do bind-like calls, so I want to put these expensive ops lazy.


Solution

  • Use pointer, preferably smart pointer.

    class A 
    {
    public:
      void foo() {
        if( pb == nullptr ) {
          pb.reset(create_B_obj());
        }
      }
    private:
      B* create_B_obj(); //or return std::unique_ptr
    
    private:
      std::unique_ptr<B> pb;
      int v;
    };
    

    You could avoid the dynamic allocation if you use placement-new instead, in which case you need custom deleter with std::unique_ptr:

    class A 
    {
    public:
      void foo() {
        if( pb == nullptr ) {
          pb.reset(create_B_obj());
        }
      }
    private:
      B* create_B_obj()
      {
         return new (buffer) B( /* arguments */);
      }
    private:
      std::unique_ptr<B, PlacementNewDeleter> pb;
      alignas(B) char buffer[sizeof(B)];  //buffer used by placement new
      int v;
    };
    

    where PlacementNewDeleter defined as:

    struct PlacementNewDeleter
    {
       template<typename T>
       void operator(T const *obj) const { obj->~T(); } 
    };
    

    Hope that helps.