你为什么要把运营商"新"设为私人运营商

Why would you ever make operator `new` private?

本文关键字:运营商 quot 为什么      更新时间:2023-10-16

我使用的是OpenSplice DDS,在那里,几乎所有的C++类(我使用的基本类,如果重要的话,我可以提到它们)都将new运算符重载为私有(以防止用户使用它们)。我不明白,为什么会有人这么做?有人能提供一些例子来说明这一点的必要性吗?

为什么我需要new:因为这些类中的大多数都没有默认构造函数,我需要在稍后的实现中通过unique_ptr初始化它们。

简单的技巧:另一方面。。。我可以很容易地骗这个!我可以用另一个类包装这个类,并使用new,对吧?因此,我不理解这种动机,感觉很糟糕。有人能解释一下吗?


编辑:

澄清一下:提供一个无法逃脱的好例子是一个很好的答案。这将有助于所有看到new运营商被私有化的人。

许多嵌入式C++需要保证系统启动后不会进行动态分配。航空、汽车和医疗器械行业经常有这样的要求。有关此类编码标准及其背后的合理性,请参阅以下链接:

  • http://www.stroustrup.com/JSF-AV-rules.pdf
  • http://www.qa-systems.com/tools/qa-misra/

为什么会有人[将new运算符重载为私有运算符(以防止用户使用它们)]

可能是为了防止直接在堆上分配对象(即动态)。

有人能提供一些例子来说明这一点的必要性吗?

我不知道有什么必要这样做。查找有关此类决策信息的最佳来源是文档。如果没有文档,那么您可以询问开发人员。

我只能猜测。我的猜测是,设计者希望通过忘记释放动态对象,或者试图破坏或使用不存在的对象,让用户更难犯错误。


EDIT:这不是官方的,但一位被标记为提供图书馆的公司员工的用户在他们的论坛上发表了评论:

ISO C++API被设计为在堆栈而不是堆上创建所有对象,因为这允许根据对象是否仍被引用自动进行所有内存管理。复制ISO C++对象不会产生开销,因为这只会复制底层智能指针,导致对同一对象的两个引用。


因为这些类中的大多数都没有默认构造函数,我需要稍后初始化它们。。。

这并不一定意味着您需要动态分配。即使一个类可能没有默认构造函数,它也可能有一个合理的默认状态,这可以通过向构造函数传递一些规范值(比如nullptr)来实现。

您并不严格需要new。

New可以被禁止强制对象的堆栈分配(与堆分配相反)。考虑:

struct Point {
int x, y;
};
Point * a = new Point{3, 5}; //sizeof(Point) in heap + sizeof(Point *) in stack.
Point b{3, 5}; //sizeof(Point), directly in the stack

因此,如果您删除操作员new(在C++11中,如果您想禁止,这是正确的方式)或将其设为私有(在C++11之前),您将为用户强制执行该协议。

禁止(但不删除)newing和构造函数的另一个原因可能是返回对象工厂的某种智能指针:

class MyClass {
private:
MyClass();
void * operator new(...);
public:
static std::shared_ptr<MyClass> create() {
//check if object in cache...
auto c = std::make_shared<MyClass>();
//Do more stuff maybe
return c;
}
};

如果需要,这将在工厂构造函数中强制执行一些东西,例如使用缓存或任何其他东西,这将禁止外部用户也使用new,但仍然允许在类内部使用new进行分配(如果删除运算符new,则不能再这样做了)。