使用 init 方法来避免使用 new 分配对象是这种糟糕的设计

Using init-methods to avoid allocating object using new - is this bad design?

本文关键字:对象 分配 方法 init new 使用      更新时间:2023-10-16

我最近开始使用init方法,而不是在C++设计类时将参数传递给构造函数:

Class A {
public:
A();
init(int number);
...
};

而不是:

Class A {
public:
A(int number);
};

这允许我在其他类中使用 A 作为成员,如下所示:

class B {
A m_a;
};

而不是我以前做的方式:

class B {
A *m_a;
};

(然后在 B 的构造函数中分配m_a。

使用 init 函数的好处是我不必担心删除 m_a,因为当 B 的实例被销毁时,它会被销毁。

我的问题是:使用我应该知道的初始化方法有什么缺点吗?这会溢出堆栈等吗?

到目前为止一切正常,但我认为在以这种方式编写大量代码之前,我应该先问一下。

>这是一个可怕的模式。

对象在其构造和调用 init 之间将处于未定义状态。此外,您还必须考虑使 init 线程安全,并在多次调用时使 init 健壮。

另请注意,从 c++11 开始,您可以从另一个构造函数调用构造函数。因此,init 函数消除了可能因拥有多个构造函数而产生的代码重复的论点不再适用。

您不必使用指针将类实例作为属性。

Class B {
public:
    explicit B(int i); // notice the explicit, btw
    A m_a;
};
B::B(int i)
    : m_a(i) { // will call the constructor of "A" with "i" as argument
}

B的实例也被销毁时,m_a将被销毁。

通过添加 init 方法,您违背了构造函数的目的:您可以拥有一个未完全构建的对象。而不是忘记删除m_a ,您冒着忘记初始化它的风险。

您可以按值存储属性,即使需要非默认构造函数来实例化它们。在类 B 的构造函数中,您需要通过初始化列表显式实例化m_a,例如 B(int number):m_a(number){} .使用初始化函数来克服这个"问题"在这里确实是不必要的,因为语言本身支持这一点。