私营新运营商是否有任何意外的副作用?

时间:2011-05-14 10:56:17

标签: c++ stack raii new-operator

我在this博客中读到,将新运算符设为私有是一种在堆栈上实施实例化的好方法。

我正在实施一个使用RAII习语的课程。这个类显然只应该在堆栈上实例化,所以我正在寻找一种强制执行的方法。

  • 我的问题是,这是否有任何不直接看到的副作用?
  • 在堆栈上强制实例化是一种好方法吗?
  • 是否存在可移植性问题?

感谢您的帮助!

修改

我的RAII类只是实例化我正在处理的框架的各个部分,因此除了在堆栈上创建实例之外,对该类执行任何其他操作都没有意义。

目标只是提供一个简单的可能性来配置框架并将其置于即用状态,而无需在客户端代码中实例化10个对象。

3 个答案:

答案 0 :(得分:7)

  

这个班级显然应该只是   在堆栈上实例化,所以我   正在寻找一种强制执行的方法。

对于用户来说,如果你必须执行它,我想这对他们来说并不明显......

主要缺点是它不起作用

即使新运算符是私有的,用户仍然可能会意外地将您的类用作其自己类的数据成员或基类,然后使用new实例化其类。当他们写Foo *f = new Foo();时,它会阻止他们写Foo f;,但它并没有强制他们使用你的RAII类符合词法范围,这可能是你真正想要强制执行的

如果有人想要使用具有动态存储持续时间的锁(或其他),那么它们要么非常聪明,要么非常愚蠢。无论哪种方式,如果你让他们自己创造它,那么你无法阻止他们绕过你的限制。

你可以做的是让所有构造函数都是私有的(包括copy ctor),然后提供一个按值返回的友元函数。他们必须写:

const Foo &f = GimmeAFoo();
标准要求的

将延长返回值的生命周期,直至f的范围。由于它们无法复制对象,因此无法使值超出引用范围。由于它们无法初始化数据成员或基类,因此无法使用该变通方法。请注意,它们必须采用const引用,因此如果您的类需要非const成员,它就不会真正起作用。

他们仍然可以做一些蠢事,比如像这样初始化他们自己的类的const引用数据成员,但对象本身不会逃避发生这种情况的范围。他们将留下一个悬挂的参考,就像他们指出他们不应该做的东西一样。

答案 1 :(得分:2)

即使你无法阻止其他人将RAII类作为基类或动态创建的对象的成员,正如史蒂夫所说,并且你应该总是告诉用户你对这个类的预期用途,它仍然是个好主意。将新操作符设为私有以防止最明显的滥用。

因为这是所有有效的C ++代码,所以没有可移植性问题。

答案 2 :(得分:2)

  

我正在实施一个使用RAII习语的课程。这个类显然只应该在堆栈上实例化,所以我正在寻找一种强制执行的方法。

那不是RAII。 RAII在析构函数中构造和去初始化时正在初始化。 RAII是关于您控制的资源(例如数据成员)而不是“父”对象的生命周期。然后,您的类型的用户再次应用RAII来控制他们分配的生命周期。例如,您可以动态分配std :: vector,即使vector使用RAII来确保清除每个项目 it “ownns”。


  

我的问题是,这是否有任何不直接看到的副作用?

是的,你阻止其他方式有效(至少就RAII而言)使用你的类型。

void example() {
  shared_ptr<T> p (new T());
  // No RAII violation, still uses operator new.

  vector<T> v (some_initial_size);
  // No RAII violation, still uses operator new (the placement form is used
  // inside the default allocator).
}

  

在堆栈上强制实例化是一种好方法吗?

你想阻止什么?用例是什么?任何使用新类型的人都知道他们正在做什么并且需要它,或者2)无论你做什么,都会严重破坏资源管理。你通过试图强制执行此操作来阻止#1中的那些人而不帮助#2中的那些人。

这是史蒂夫所说的另一种方式:

  

这个类显然只能在堆栈上实例化,所以我正在寻找一种强制执行的方法。

如果这是显而易见的,为什么需要强制执行?

如果用户盲目使用“new T()”,是什么让你觉得他们不会盲目地使用“:: new T()”?


  

目标只是提供一个简单的可能性来配置框架并将其置于即用状态,而无需在客户端代码中实例化10个对象。

#include <framework>

int main() {
  framework::Init init;
  // Do stuff.
}

在您的文档示例中突出显示使用此内容或与其非常接近的内容。