在我目前正在阅读的这本书中,我遇到了这个问题:
类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。
从上面推断编译器在某些情况下不会为类/结构生成默认构造函数,我是否正确?如果是,这些情况是什么?我会冒险说 POD 可能就是其中之一。还有其他的吗?
编辑:我更改了标题,因为原始标题的含义是我问什么时候没有定义默认构造函数,而不是问一个类什么时候根本没有构造函数。
在我目前正在阅读的这本书中,我遇到了这个问题:
类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。
从上面推断编译器在某些情况下不会为类/结构生成默认构造函数,我是否正确?如果是,这些情况是什么?我会冒险说 POD 可能就是其中之一。还有其他的吗?
编辑:我更改了标题,因为原始标题的含义是我问什么时候没有定义默认构造函数,而不是问一个类什么时候根本没有构造函数。
类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。
我认为作者是在谈论这种情况:
some_type some_function () {
POD_type this_is_intentionally_uninitialized;
...
}
在某些情况下,不会调用构造函数,句号。一旦您编写了构造函数,您就没有 POD 类,因此现在将调用构造函数。
让一个包含随机、未初始化数据的对象到处乱跑是好事还是坏事,这完全是一个不同的问题。
始终声明默认构造函数。但它并不总是被定义。只有当它被使用时,编译器(或你)才会定义它。例子:
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
如果您总是使用带参数的构造函数创建类的对象,则不需要默认构造函数。
编译器为每个类生成一个默认构造函数,但如果您为该类定义自己的构造函数,则编译器不会自行生成默认构造函数。只要您通过您提供的构造函数创建此类的对象,该类就不需要并且具有默认构造函数。
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。
在我看来,这句话意味着您不必总是编写自己的默认构造函数,因为某些类可能不需要默认初始化。
例如,如果您的类包含多个提供它们自己的默认构造函数的类字段,则您不需要编写任何默认构造函数,因为默认情况下无论如何都会调用成员的构造函数。
与此相反,您可能希望编写一个struct
或一个class
POD,依靠程序员手动正确初始化其字段;在这种情况下,您可能不会编写默认构造函数,因此编译器将编写自己的构造函数,将这些字段保留为其默认的未初始化值(实际上,它将是空操作,并且可能会被优化掉)。
如果您没有提供任何构造函数,编译器只会声明和定义一个自动生成的默认构造函数。
但是,对于不可实例化的父类,可以阻止任何类型的构造函数工作。通过添加一个带有虚拟参数的虚拟构造函数,可以只杀死自动生成的默认构造函数,但代价是更多的繁文缛节。
你的问题有一定的歧义。您会看到,编译器对构造函数采取的隐式操作涉及声明它们和定义它们。如果声明了一些构造函数但没有定义,你认为它存在还是不存在?
无论如何,没有办法创建一个没有为其声明构造函数的类。例如,复制构造函数总是被声明的。没有办法压制它。如果你自己不声明,编译器会为你声明。
至于默认构造函数 - 可以禁止其隐式声明。如果您自己声明任何构造函数(即显式),编译器不会隐式声明默认构造函数。但是在这种情况下,你的类当然会有一个构造函数:你自己声明的那个。(另外,正如我上面所说,复制构造函数总是被声明的)。
至于隐式定义的构造函数......它们只有在您使用它们时才由编译器定义。当然,它们只有在可能的情况下才会被定义。(如果您使用隐式构造函数,并且被证明无法定义,那么您的程序将无法编译)。
因此,再一次,当涉及到已声明的构造函数时,根本不可能有一个没有构造函数的类。任何类都至少有一个为它声明的构造函数。
如果您对定义的构造函数特别感兴趣,那么确实有可能拥有一个没有定义构造函数的类。这是一个给你的例子
struct S {
S(const S&);
};
就是这样。该类有一个声明它的构造函数,但它没有定义:)
如果声明了另一个构造函数,则不会为类定义默认构造函数。
对于 POD 类型(在普通和标准布局的意义上,因为这些术语在 C++11 中定义),编译器是否生成构造函数是一个有争议的问题,因为编译器生成的构造函数是微不足道的。有关详细信息,请查看什么是聚合和 POD 以及它们如何/为什么特别?
所以简单地说 - (在 CPP 的上下文中)如果没有定义构造函数,那么编译器就没有默认构造函数。它仅在需要时由编译器定义。
在某些情况下,它是由编译器完成的。其中一些是 -
我们有一个容器对象。下面的代码解释了这一点。
class Legs
{
ctor(); // ctor stands for constructor
};
class cat
{
Legs leg;
public:
cat(){}
};
在虚函数的情况下,将虚表指针设置为正确的 V-Table 是在 Constructor 中完成的。出于这个原因,默认构造函数将由编译器定义。
some_type some_function () { POD_type this_is_intentionally_uninitialized; ... }