Question

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.

Was it helpful?

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.

OTHER TIPS

If you don't have access on the B class, then the easier way to do this is to use a pointer.

std::unique_ptr<B> b;

Then if your foo method:

B foo()
{
    if (! b)
        b.reset(new B(/* params */));
        // or  b.reset(create_B_obj());, which should return a pointer (may also return an unique_ptr)
    return b;
}

The std::unique_ptr overloads operator bool and manages the memory so you don't have to delete.

Note: I changed the return type of the foo method as it seems more logical like this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top