C++对象模型之默认构造函数

在不声明自定义构造函数时,编译器会自动生成一个默认构造函数。但是这个默认构造函数有可能是一个trivial(无用的) constructor,也可能是nontrivial constructor。

举个例子

class Foo {
    public:
        int val;
        Foo* pnext;
}  

void foo_bar()
{
     Foo bar;
     if(bar.val || bar.pnext)
          //...do something
} 

之前的想法是Foo有一个默认构造函数,可以将var和pnext初始化为0。

其实不然。

原因是将两个members初始化为0,并不是编译器所需要的。也就是说,编译器合成了一个默认构造函数是trivial constructor,不会对两个members做初始化。

那么什么情况下,编译器会合成nontrivial constructor?四种情况。

1、带有Default Constructor的Member Class Object

类中的一个member object有default constructor。

class Foo {
public:
     Foo();
     Foo(int);
}  

class Bar
{
public:
     Foo foo;
     char* str;
}

当创建Bar对象时,需要调用Bar的默认构造函数。被合称的默认构造函数需要能够调用Class Foo的 的默认构造,处理Bar::foo。

但是它并不产生任何代码初始化Bar::str。正如前面所说,初始化foo是编译器的责任,初始化str是程序员的责任。

如果为了初始化str,我们定义自己的构造函数:

Bar::Bar() {str = 0;}

此时编译器不会为我们合成默认构造函数,那么是如何实现上面的初始化foo的工作呢?

原来编译器会扩张已存在的constructors,在其中安插代码,在user code之前,根据member objectsd的声明次序,依次调用必要的default constructors。

类似这样:

Bar::Bar()
{
     foo.Foo::Foo();
     str = 0;
}

2、带有Default Constructor的Base Class

一个没有任何构造函数的类派生自一个带有default constructor的父类,那么这个派生类的默认构造函数是nontrivial的。 它将调用base class的default constructor。

和上一条类似,当设计者提供多个构造函数时,编译器会扩张现有构造函数,在最开始调用base class constructor。

3、带有一个Virtual Function的Class

a) class声明或继承一个virtual function。

b)class派生自一个继承链,其中有一个或多个virtual base function。

下面两个扩张操作会在编译期间发生:

1、一个virtual function table。里面保存class的virtual functions地址

2、每个class object中的vptr,保存的是class vtbl的地址。

4、带有一个 Virtual Base Class的Class

原文地址:https://www.cnblogs.com/jimobuwu/p/8991613.html

时间: 2024-11-25 18:16:50

C++对象模型之默认构造函数的相关文章

C++对象模型之默认构造函数的构造操作

一个类,如果没有任何的用户声明的的构造函数,那么会有一个默认的构造函数被隐式地声明出来.这个被隐式声明的构造函数,究竟什么时候被合成.被编译器合成的默认构造函数究竟执行怎么样的操作,编译器如何处理用户定义的构造函数,就是本文要探讨的问题. 1.默认构造函数何时被合成 如果一个类没有任何的用户声明的构造函数,那么在当编译器需要的时候,编译器会为类合成一个默认的构造函数,它只用于执行编译器所需要的操作.注意,默认的构造函数是在编译器需要的时候被合成出来,而不是程序需要的时候,如果程序需要,则默认的构

【C++对象模型】构造函数语意学之一 默认构造函数

默认构造函数,如果程序员没有为类定义构造函数,那么编译器会在[需要的时候]为类合成一个构造函数,而[需要的时候]分为程序员需要的时候和编译器需要的时候,程序员需要的时候应该由程序员来做工作,编译器需要的时候则由编译器来做工作. C++中,全局变量 / 对象的内存会被清零(如果类对象没有程序员定义的构造函数的时候), 而堆heap 或 栈stack上的变量或对象则不会被清零,其内存只取决于上一次这段内存的值. 而编译器什么情况下会为类合成默认构造函数呢?会在以下四种情况合成默认的构造函数: 1.类

C++ 合成默认构造函数的真相

对于C++默认构造函数,我曾经有两点误解: 类如果没有定义任何的构造函数,那么编译器(一定会!)将为类定义一个合成的默认构造函数. 合成默认构造函数会初始化类中所有的数据成员. 第一个误解来自于我学习C++的第一本书 <C++ Primer>,在书中392页:“只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数”. 实际上这句话也没有说错,它说明了默认构造函数定义的必要非充分条件,然而却给当时初学C++的我造成了一定的误解. 第二个误解依旧来自于Primer中的一句话:“合成的

默认构造函数的构造操作

以下四种情况,编译器将会合成(即由编译器负责)一个nontrivial默认构造函数. 1.成员对象带有默认构造函数 例如: #include <iostream> using namespace std; class Foo { public: Foo() { cout << "Foo" << endl; } // Foo类含有默认构造函数 }; class Bar { public: Foo foo; int x; }; int main() {

C++默认构造函数的一点说明

大多数C++书籍都说在我们没有自己定义构造函数的时候,编译器会自动生成 默认构造函数.其实这句话我一直也是深信不疑.但是最近看了一些资料让我 有了一点新的认识. 其实我觉得大多数C++书籍之所以这样描述其实是玩了文字游戏的.如果说编译器 自动产生的默认构造函数对于我们的类没有任何作用,也就是说在编译器默认生成 的这个构造函数里根本没有任何实质性的代码工作,那么这种默认构造其实是可有 可无的,所以不妨说编译器其实是为每个类生成了默认构造函数的. 在深度探索C++对象模型中讲了四种关于编译器自动生成

深度探索C++对象模型 第二章构造函数语意学

在使用C++时,常常会好奇或者抱怨,编译器为我们做了什么事呢? 为什么构造函数没有为我初始化呢?为什么我还要写默认构造函数呢? 2.1 Default Constructor 的构造操作 如果没有声明默认构造函数,编译器会在需要的时候帮我们产生出来. 为了避免在多个地方被需要导致重复,则编译器将产生的构造函数声明为inline方式. class Foo {public:Foo(), Foo(int) }; class Bar {public: Foo foo;char *str;} Bar ba

C++编译器合成默认构造函数和复制控制成员(拷贝构造函数,赋值操作符,析构函数)的条件

(参考自<深入理解C++对象模型>) ”C++新手一般有两个常见的误解: 任何class如果没有定义default constructor,就会被合成一个出来. 编译器合成出来的default constructor会明确设定class 内每一个data member的默认值.” 现在主要解释第一条为什么是错误的,根据<深入理解C++对象模型>,”default constructor 在需要的时候被编译器产生出来”,以下就是4种”需要的时候”: 1). 该类含有一个成员对象而后者

【C/C++】构造函数、默认构造函数、成员初始化列表

常见问题 Q1. 下列关于构造函数的描述中,错误的是( ) A. 构造函数可以设置默认的参数 B. 构造函数在定义类对象时自动执行 C. 构造函数可以是内联函数 D. 构造函数不可以重载 Q2. 下列代码中a.b的各个成员变量值是多少? 1 class Student 2 { 3 public: 4 Student() {} 5 void show(); 6 private: 7 string name; 8 int number; 9 int score; 10 }; 11 Student a

编译器生成默认构造函数的情况

在类没有显示声明构造函数的情况下,编译器并不总是为我们自动生成默认构造函数,以下4种情况,编译器才会为我们自动生成默认构造函数: 1.类中有一个类成员含有默认构造函数的,编译器会为该类自动生成默认构造函数,自动插入代码,调用该成员的构造函数: 2.基类中含有默认构造函数,编译器会为该类自动生成默认构造函数,自动插入代码,调用基类的构造函数: 3.类中含有虚函数时,由于编译器要为该类生成虚函数表vtable,并为该类的对象生成指向该vtable的vptr,所以需要为该类合成默认构造函数: 4.虚继