代码之家  ›  专栏  ›  技术社区  ›  Tall Jeff

何时调用成员数据构造函数?

  •  0
  • Tall Jeff  · 技术社区  · 5 年前

    我有一个全局成员数据对象,在头(对于类mymainobj)中定义,如下所示。

    class MyMainObj
    {
        MyDataObj obj;
    }
    

    MyDataObj 具有默认构造函数。 什么时候施工 MyDATAOBO 打电话? 它被称为 MyMainObj ?

    7 回复  |  直到 15 年前
        1
  •  2
  •   rlbond    15 年前

    在本例中,mydataobj不是mymainobj的成员,它是一个局部变量。

    但是,在类的构造函数中调用数据成员的构造函数。在执行到达构造函数的第一行之前调用每个成员的默认构造函数, 除非 使用 初始化列表 ,在这种情况下,将改为调用该构造函数。

        2
  •  3
  •   Jerry Coffin    15 年前

    有了这个代码, obj 不是mymainobj的成员——它只是该构造函数内的本地对象。因此,只有当/如果调用该构造函数时,才会构造它。

        3
  •  3
  •   GManNickG    7 年前

    关于您的代码,您有一个包含变量的函数。输入函数后,将运行到声明变量的代码行,然后运行构造函数。

    但你说的是“我的主要对象的创造”。它是一个函数,只能调用,不能创建。


    这都与标题问题有关,“何时构建成员?”如果 MyMainObj 是类而不是函数。

    成员对象是按照它们在类声明中出现的顺序构造的。所有对象在进入构造函数时都是完全构造的。(但这不包括类本身!)

    也就是说,到类进入其构造函数时,所有成员都已完成其构造函数。

    在析构函数中(在析构函数运行之后),对象按相反的顺序被销毁。

    在伪图中:

    MyClass
        Member1
        Member2
        Member3
    
    Construction:
        Member1
        Member2
        Member3
        MyClass
    
    Destruction:
        MyClass
        Member3
        Member2
        Member1
    

    可以使用初始化列表手动调用成员构造函数:

    class foo
    {
    public:
        foo(void) : i(0) // construct i with 0.
        {
        }
    
        int i;
    };
    

    关于初始化列表,有各种各样的问题。 Initialization list order , Copy-construction initialization list , and more .

        4
  •  0
  •   Eric Petroelje    15 年前

    是的,每当创建MyMaiNobj实例时都会调用构造函数。

    我对“全局成员”术语有点困惑——您声明对象的方式——它将是构造函数内的局部变量。我是不是错过了什么?

        5
  •  0
  •   Klaim    15 年前

    是的,正如其他说明的,成员将在创建所有者类、构造(由编译器生成或使用提供的构造函数生成)时创建。

    创建顺序将与您的成员在类声明中的apear相同。例如:

    class MyType
    {
        Thing a;
        Thing b;
        Thing d;
        Thing c;
     };
    

    无论使用什么构造函数,无论初始化列表中的顺序是什么,成员都将按以下顺序构造:a、b、d、c。一旦完成了所有操作,将执行构造函数代码(如果存在),然后才构造整个对象。

        6
  •  0
  •   Gorpik    15 年前

    在输入对象构造函数时,已经为其分配了内存。执行顺序如下:

    1. 初始化列表中指定的基类构造函数(如果有);如果未指定,则使用默认构造函数。

    2. 在初始化列表中指定的成员数据的构造函数(如果未指定,则为默认值),其顺序与类定义中声明的顺序相同。在初始化列表中指定它们的顺序是不相关的。

    3. 构造函数主体。

    在问题中的示例集中,在输入 MyMnObjo 将是的默认构造函数 我的数据对象 构造成员数据 OBJ .

        7
  •  0
  •   colgur    15 年前

    授课 A :

    class A {
        MyDataObj obj;
    }
    

    如果不为编写构造函数 A ,编译器将为您创建一个,它将创建 obj 作为施工的一部分 (毁灭) OBJ 作为破坏的一部分 .

    如果您确实为 A 然后 OBJ 将在构造函数运行之前创建,尽管您可以重新分配它:

    class A {
        MyDataObj obj;
      public:
        A() { } // obj created, but the value may or may not be predictable
    }
    
    class AA {
        MyDataObj obj;
      public:
        AA()
        {
            obj = MyDataObj(5);
        }
    }
    
    class AAA {
        MyDataObj obj;
      public:
        AAA() : obj(5) { } // member initializer list, my preferred method
    }
    

    使用第三个选项,将在运行成员初始值设定项列表之前创建数据对象,并按声明的顺序分配值。 AAA , 不是 它们在成员初始值设定项列表中列出的顺序。

    更新 :创建和初始化之间存在差异。数据成员(以及基类,以及基类的数据成员)的空间总是被留出的——我称之为“创建”。但是,这并不意味着一个有用的值存储在内存中。 There are separate rules for whether an object is default initialized ,这取决于数据成员的类型(原语、pod、非pod)和主对象的存储类(本地、静态、全局)。避免这方面的意外最简单的方法就是确保显式初始化所有内容。