如何在 C++ 中进行惰性构造?

xun*_*ang 1 c++ sockets constructor default-constructor lazy-initialization

我想在 C++ 类中进行“懒惰构造”,一个简单的方法是这样的:

#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;
};
Run Code Online (Sandbox Code Playgroud)

但是存在的一个问题是 B 可能不包含默认构造函数 ( B()),那么在这种情况下我该如何做“懒惰构造”呢?

顺便说一句:我项目中的 B 类就像一个套接字,需要进行连接或类似绑定的调用,所以我想把这些昂贵的操作懒惰。

Naw*_*waz 5

使用指针,最好是智能指针。

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;
};
Run Code Online (Sandbox Code Playgroud)

如果您改用placement-new,您可以避免动态分配,在这种情况下,您需要自定义删除器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;
};
Run Code Online (Sandbox Code Playgroud)

其中PlacementNewDeleter定义为:

struct PlacementNewDeleter
{
   template<typename T>
   void operator(T const *obj) const { obj->~T(); } 
};
Run Code Online (Sandbox Code Playgroud)

希望有帮助。