member(“:”)语法在构造函数中?

最近我看到一个例子如下:

#include <iostream>

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

int main(void) {
  std::cout << Foo(42).bar << std::endl;
  return 0;
}

这有什么奇怪的: bar(num)是什么意思? 它似乎初始化成员变量,但我从来没有见过这种语法。 它看起来像一个函数/构造函数调用,但为int ? 对我来说毫无意义。 也许有人可以启发我。 顺便说一下,是否还有其他深奥的语言特征,在普通的C ++书籍中你永远找不到?


这是一个成员初始化列表。 你应该在任何优秀的C ++书籍中找到关于它的信息。

在大多数情况下,您应该初始化成员初始化列表中的所有成员对象(但是,请注意FAQ条目末尾列出的例外情况)。

FAQ条目的关键点在于,

所有其他的事情都是平等的,如果你使用初始化列表而不是赋值,你的代码将运行得更快。


Foo(int num): bar(num)    

这个构造在C ++中被称为成员初始化列表

简单地说,它会将您的成员bar 初始化为值num


构造函数中的Initializing和Assignment有什么区别?

成员初始化:

Foo(int num): bar(num) {};

成员任务:

Foo(int num)
{
   bar = num;
}

使用成员初始值设定项列表初始化一个成员,并在构造函数体内为其赋值。

当你通过成员初始化列表初始化字段时,构造函数将被调用一次,并且该对象将在一次操作中被构造和初始化。

如果您使用赋值,则字段将首先使用默认构造函数进行初始化,然后通过赋值运算符重新赋值实际值。

正如你看到的那样,在后者中还有额外的创建和分配开销,这对用户定义的类可能相当重要。

Cost of Member Initialization = Object Construction 
Cost of Member Assignment = Object Construction + Assignment

后者实际上相当于:

Foo(int num) : bar() {bar = num;}

前者相当于只是:

Foo(int num): bar(num){}

对于内置的(您的代码示例)或POD类成员,没有实际的开销。


你什么时候需要使用成员初始化列表?

如果出现以下情况,您将( 有必要)使用成员初始值设定项列表:

  • 你的课有一个参考成员
  • 你的类有一个非静态的const成员或
  • 你的类成员没有默认的构造函数或
  • 用于初始化基类成员或
  • 当构造函数的参数名称与数据成员相同时(这不是必须的)

  • 代码示例:

    class MyClass
    {
        public:
            //Reference member, has to be Initialized in Member Initializer List
            int &i;       
            int b;
            //Non static const member, must be Initialized in Member Initializer List
            const int k;  
    
        //Constructor’s parameter name b is same as class data member 
        //Other way is to use this->b to refer to data member
        MyClass(int a, int b, int c):i(a),b(b),k(c)
        {
             //Without Member Initializer
             //this->b = b;
        }
    };
    
    class MyClass2:public MyClass
    {
        public:
            int p;
            int q;
            MyClass2(int x,int y,int z,int l,int m):MyClass(x,y,z),p(l),q(m)
            {
            }
    
    };
    
    int main()
    {
        int x = 10;
        int y = 20;
        int z = 30;
        MyClass obj(x,y,z);
    
        int l = 40;
        int m = 50;
        MyClass2 obj2(x,y,z,l,m);
    
        return 0;
    }
    
  • MyClass2没有默认的构造函数,所以它必须通过成员初始化列表进行初始化。
  • 基类MyClass没有默认构造函数,所以初始化它的成员将需要使用成员初始化列表。
  • 在线版本的代码示例


    使用成员初始化程序列表时要注意的要点:

    类成员变量总是按照它们在类中声明的顺序进行初始化。

    它们没有按照成员启动程序列表中指定的顺序进行初始化。
    简而言之,成员初始化列表不确定初始化的顺序。

    鉴于上述情况,始终保持成员初始化顺序与其在类定义中声明的顺序一致是一种很好的做法。 这是因为编译器不会警告两个订单是否不同,但相对较新的用户可能会将成员初始化程序列表混淆为初始化顺序,并根据该顺序编写一些代码。


    这是构造函数初始化。 这是在类构造函数中初始化成员的正确方法,因为它可以防止默认的构造函数被调用。

    考虑这两个例子:

    // Example 1
    Foo(Bar b)
    {
       bar = b;
    }
    
    // Example 2
    Foo(Bar b)
       : bar(b)
    {
    }
    

    在例1中:

    Bar bar();  // default constructor
    bar = b;  // assignment
    

    在例2中:

    Bar bar(b) // copy constructor
    

    这关乎效率。

    链接地址: http://www.djcxy.com/p/40233.html

    上一篇: member (" : ") syntax in the constructor?

    下一篇: C function syntax, parameter types declared after parameter list