在PIMPL习语中使用引用的利弊

mem*_*64k 3 c++ design-patterns

如前所述在这里你可以使用引用(d-参考),代替指针(d-指针中的情况下)PIMPL方法.

我试图了解这个实现是否存在任何严重问题以及优缺点是什么.

优点:

  • 由于使用"."而缩短了语法.而不是" - >".
  • ...

缺点:

  • 如果新的ObjectPivate()失败并且new没有抛出(例如:new(std :: nothrow)或custom new)并返回nullptr怎么办?您需要实现其他内容来检查referance是否有效.如果你只是使用指针:

if (m_Private)
  m_Private->Foo();

  • 在具有复杂初始化逻辑的Object的多个构造函数的极少数情况下,解决方案可能不适用.[©JamesKanze]
  • 它更自然地使用指针进行内存管理.[©JamesKanze]
  • 需要考虑一些额外的实现细节(使用swap())来确保异常安全(例如赋值运算符的实现)[©Matt Yang]
  • ...

这里的示例代码用于说明:

// Header file

class ObjectPrivate;

class Object
{
public:
 Object();
 virtual ~Object();

 virtual void Foo();

 private:
   ObjectPrivate&  m_Private;
};

// Cpp file

class ObjectPrivate
{
public:
  void Boo() { std::cout << "boo" << std::endl; }
};

Object::Object() :
m_Private(* new ObjectPrivate())
{
}

Object::~Object()
{
  delete &m_Private;
}

void Object::Foo()
{
  m_Private.Boo();
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*nze 6

这真的只是风格问题.我倾向于不在类中使用引用,所以在编译防火墙中使用指针似乎更自然.但是,通过这种或那种方式通常没有真正的优势:只能通过例外new来 失败.

你可能喜欢指针的一种情况是当对象有很多不同的构造函数时,其中一些需要在调用之前进行初步计算new.在这种情况下,您可以使用NULL,初始化指针,然后调用常见的初始化例程.不过,我认为这种情况很少见.(我已经遇到过一次,我记得.)

编辑:

只是另一种风格考虑:很多人不喜欢这样的东西delete &something;,如果你使用引用而不是指针需要它.同样,管理内存的对象使用指针似乎更自然(至少对我来说).