gpt4 book ai didi

c++ - 构造函数中这个奇怪的冒号成员 (": ") 语法是什么?

转载 作者:bug小助手 更新时间:2023-10-28 01:31:51 25 4
gpt4 key购买 nike

最近我看到了一个类似下面的例子:

#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++ 书中找不到?

最佳答案

Foo(int num): bar(num)    

此构造在 C++ 中称为 成员初始化器列表

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


构造函数内部的初始化和赋值有什么区别?

成员初始化:

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

成员分配:

Foo(int num)
{
bar = num;
}

使用成员初始化器列表初始化成员与在构造函数主体内为其分配值之间存在显着差异。

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

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

如您所见,后者有额外的创建和分配开销,这对于用户定义的类来说可能是相当大的。

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 类成员,没有实际开销。


什么时候必须使用成员初始化器列表?

如果出现以下情况,您将(相当被迫)使用成员初始化器列表:

  • 您的类(class)有一个引用成员
  • 您的类有一个非静态 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 没有默认构造函数,因此要初始化其成员,需要使用成员初始化器列表。

使用成员初始化器列表时的注意事项:

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

它们按照它们在成员初始化器列表中指定的顺序进行初始化。
总之,Member 初始化列表不决定初始化的顺序。

鉴于上述情况,保持成员初始化的成员顺序与在类定义中声明它们的顺序相同始终是一个好习惯。这是因为如果这两个顺序不同,编译器不会发出警告,但相对较新的用户可能会将成员 Initializer 列表混淆为初始化顺序并编写一些依赖于此的代码。

关于c++ - 构造函数中这个奇怪的冒号成员 (": ") 语法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1711990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com