8

在我目前正在阅读的这本书中,我遇到了这个问题:

类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

从上面推断编译器在某些情况下不会为类/结构生成默认构造函数,我是否正确?如果是,这些情况是什么?我会冒险说 POD 可能就是其中之一。还有其他的吗?

编辑:我更改了标题,因为原始标题的含义是我问什么时候没有定义默认构造函数,而不是问一个类什么时候根本没有构造函数。

4

9 回答 9

8

类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

我认为作者是在谈论这种情况:

some_type some_function () {
   POD_type this_is_intentionally_uninitialized;
   ...
}

在某些情况下,不会调用构造函数,句号。一旦您编写了构造函数,您就没有 POD 类,因此现在将调用构造函数。

让一个包含随机、未初始化数据的对象到处乱跑是好事还是坏事,这完全是一个不同的问题。

于 2011-08-20T15:08:52.607 回答
5

始终声明默认构造函数。但它并不总是被定义。只有当它被使用时,编译器(或你)才会定义它。例子:

struct A { std::string str; };
// not yet defined

struct B : A { };
// not yet defined

B b; 
// Now B::B and A::A are defined

请注意,这具有直接的实际后果

struct A { private: A(); };
struct B : A { };
// valid, as B::B is not yet defined

B b; 
// now invalid, because B::B is defined and tries to call a 
// private base class constructor
于 2011-08-20T13:23:33.130 回答
3

如果您总是使用带参数的构造函数创建类的对象,则不需要默认构造函数。

编译器为每个类生成一个默认构造函数,但如果您为该类定义自己的构造函数,则编译器不会自行生成默认构造函数。只要您通过您提供的构造函数创建此类的对象,该类就不需要并且具有默认构造函数。

class Myclass
{
    int m_i;
    public:
        Myclass(int i)
        {
            m_i = i;
        }

};

int main()
{
    Myclass obj1(10); // #1, uses overloaded constructor
    Myclass obj2; //#2, Will generate compiler error of no matching constructor
    return 0;
}

在上述示例的上下文中,请考虑书中的引文:

类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

在上面的示例中,只要Myclass使用#1 创建的对象,该类就不需要并且具有默认构造函数。

如果对象的Myclass创建方式需要默认构造函数,则需要为类定义默认构造函数,即:#2。

于 2011-08-20T13:23:14.973 回答
0

在我看来,这句话意味着您不必总是编写自己的默认构造函数,因为某些类可能不需要默认初始化。

例如,如果您的类包含多个提供它们自己的默认构造函数的类字段,则您不需要编写任何默认构造函数,因为默认情况下无论如何都会调用成员的构造函数。

与此相反,您可能希望编写一个struct或一个classPOD,依靠程序员手动正确初始化其字段;在这种情况下,您可能不会编写默认构造函数,因此编译器将编写自己的构造函数,将这些字段保留为其默认的未初始化值(实际上,它将是空操作,并且可能会被优化掉)。

于 2011-08-20T13:27:06.893 回答
0

如果您没有提供任何构造函数,编译器只会声明和定义一个自动生成的默认构造函数。

但是,对于不可实例化的父类,可以阻止任何类型的构造函数工作。通过添加一个带有虚拟参数的虚拟构造函数,可以只杀死自动生成的默认构造函数,但代价是更多的繁文缛节。

于 2011-08-20T17:23:57.107 回答
0

你的问题有一定的歧义。您会看到,编译器对构造函数采取的隐式操作涉及声明它们和定义它们。如果声明了一些构造函数但没有定义,你认为它存在还是不存在?

无论如何,没有办法创建一个没有为其声明构造函数的。例如,复制构造函数总是被声明的。没有办法压制它。如果你自己不声明,编译器会为你声明。

至于默认构造函数 - 可以禁止其隐式声明。如果您自己声明任何构造函数(即显式),编译器不会隐式声明默认构造函数。但是在这种情况下,你的类当然会有一个构造函数:你自己声明的那个。(另外,正如我上面所说,复制构造函数总是被声明的)。

至于隐式定义的构造函数......它们只有在您使用它们时才由编译器定义。当然,它们只有在可能的情况下才会被定义。(如果您使用隐式构造函数,并且被证明无法定义,那么您的程序将无法编译)。

因此,再一次,当涉及到已声明的构造函数时,根本不可能有一个没有构造函数的类。任何类都至少有一个为它声明的构造函数。

如果您对定义的构造函数特别感兴趣,那么确实有可能拥有一个没有定义构造函数的类。这是一个给你的例子

struct S {
  S(const S&);
};

就是这样。该类有一个声明它的构造函数,但它没有定义:)

于 2011-08-20T22:30:27.333 回答
0

如果声明了另一个构造函数,则不会为类定义默认构造函数。

对于 POD 类型(在普通和标准布局的意义上,因为这些术语在 C++11 中定义),编译器是否生成构造函数是一个有争议的问题,因为编译器生成的构造函数是微不足道的。有关详细信息,请查看什么是聚合和 POD 以及它们如何/为什么特别?

于 2016-01-12T13:20:45.760 回答
0

所以简单地说 - (在 CPP 的上下文中)如果没有定义构造函数,那么编译器就没有默认构造函数。它仅在需要时由编译器定义。

在某些情况下,它是由编译器完成的。其中一些是 -

  1. 当我们有一个具有基类对象作为成员的类时(并且未定义派生类构造函数)。在这种情况下,将创建派生类的默认构造器,因为其构造器的序言需要调用基类构造器。
  2. 我们有一个容器对象。下面的代码解释了这一点。

    class Legs
    {
    ctor(); // ctor stands for constructor
    };
    class cat
    {
    Legs leg;
    public:
    cat(){}
    };
    
  3. 在虚函数的情况下,将虚表指针设置为正确的 V-Table 是在 Constructor 中完成的。出于这个原因,默认构造函数将由编译器定义。

于 2016-09-14T10:07:10.633 回答
-1

some_type some_function () { POD_type this_is_intentionally_uninitialized; ... }

于 2018-01-30T10:57:51.670 回答