Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 构造函数中这种奇怪的冒号成员(“:”)语法是什么?_C++_Syntax_Constructor_C++ Faq_Ctor Initializer - Fatal编程技术网

C++ 构造函数中这种奇怪的冒号成员(“:”)语法是什么?

C++ 构造函数中这种奇怪的冒号成员(“:”)语法是什么?,c++,syntax,constructor,c++-faq,ctor-initializer,C++,Syntax,Constructor,C++ Faq,Ctor Initializer,最近我看到了如下示例: #include <iostream> class Foo { public: int bar; Foo(int num): bar(num) {}; }; int main(void) { std::cout << Foo(42).bar << std::endl; return 0; } #包括 福班{ 公众: int-bar; Foo(intnum):bar(num){}; }; 内部主(空){ std::c

最近我看到了如下示例:

#include <iostream>

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

int main(void) {
  std::cout << Foo(42).bar << std::endl;
  return 0;
}
#包括
福班{
公众:
int-bar;
Foo(intnum):bar(num){};
};
内部主(空){
std::cout这是一个成员初始化列表。您应该在任何目录中找到有关它的信息

(但是,请注意FAQ条目末尾列出的例外情况)

FAQ条目的要点是

在所有其他条件相同的情况下,如果使用初始化列表而不是赋值,代码运行速度会更快


你是对的,这确实是一种初始化成员变量的方法。我不确定这是否有什么好处,除了清楚地表示这是一种初始化。使用“bar=num”代码内部可能更容易被移动、删除或误解。

我不知道你怎么会错过这个,它非常基本。这是初始化成员变量或基类构造函数的语法。它适用于普通的旧数据类型以及类对象。

这是构造函数初始化。它是rect初始化类构造函数中成员的方法,因为它防止调用默认构造函数

考虑以下两个例子:

// 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

这都是关于效率的。

这称为初始化列表。这是初始化类成员的一种方法。使用它有好处,而不是简单地在构造函数体中为成员分配新值,但是如果类成员是常量或引用,则必须对其进行初始化。

这是一个ini初始化列表。它将在运行构造函数体之前初始化成员。 考虑

vs

在第一个示例中,str将由其无参数构造函数初始化

string();
string( const string& s );
在Foo构造函数的主体之前

string& operator=( const string& s );
将像调用str=p一样调用“str”

在第二个示例中,str将由 调用其构造函数

string();
string( const string& s );

以“p”作为参数。

还有另一个“好处”


如果成员变量类型不支持null初始化,或者它是一个引用(不能进行null初始化),那么您别无选择,只能提供一个初始化列表

另一个已经向您解释过的语法称为“构造函数初始化器列表”。此语法允许您自定义初始化类的基子对象和成员子对象(而不是允许它们默认初始化或保持未初始化)

<>我想注意的是,正如你所说的,语法看起来像是构造函数调用,不一定是构造函数调用。在C++语言中,<>代码>(/>代码>语法只是初始化语法的一种标准形式。对于不同的类型,它的解释是不同的。对于具有用户定义的构造函数的类类型,它意味着一件事。(它实际上是一个构造函数调用),对于没有用户定义构造函数的类类型,它意味着另一件事(所谓的)空
()
),而对于非类类型,它又意味着另一件事(因为非类类型没有构造函数)


在您的情况下,数据成员的类型为
int
int
不是类类型,因此它没有构造函数。对于类型
int
,此语法仅表示“使用
num
的值初始化
bar
”就是这样。直接这样做,不涉及构造函数,因为,再一次,
int
不是类类型,因此它不能有任何构造函数。

这不是晦涩难懂的,它是


基本上,在您的情况下,
x
将用
\ux
初始化,
y
\uy
z
\uz
初始化,这是构造函数的初始化列表。不是默认地构造
x
y
z
,然后将在pa中接收到的值分配给它们参数,这些成员将立即用这些值初始化。这对于
float
s似乎不是非常有用,但对于构造成本高昂的自定义类来说,它可以节省大量时间

Foo(int num): bar(num)    

此构造在C++中被称为<强>成员初始化器列表> 简单地说,它将您的成员

bar
初始化为
num


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

Foo(int num): bar(num) {};
Foo(int num)
{
   bar = num;
}
成员分配:

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


何时必须使用成员初始值设定项列表? 如果出现以下情况,您将不得不使用成员初始值设定项列表:

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

代码示例:
我的班级