C++ 构造函数名称后面的冒号有什么作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1272680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:25:02  来源:igfitidea点击:

What does a colon following a C++ constructor name do?

c++constructorinitialization-listctor-initializer

提问by spencewah

What does the colon operator (":") do in this constructor? Is it equivalent to MyClass(m_classID = -1, m_userdata = 0);?

冒号运算符 (":") 在此构造函数中有何作用?它相当于MyClass(m_classID = -1, m_userdata = 0);?

class MyClass {
public:

    MyClass() : m_classID(-1), m_userdata(0) { 
    }

    int m_classID;
    void *m_userdata;
};

回答by Daniel Daranas

This is an initialization list, and is part of the constructor's implementation.

这是一个初始化列表,是构造函数实现的一部分。

The constructor's signature is:

构造函数的签名是:

MyClass();

This means that the constructor can be called with no parameters. This makes it a default constructor, i.e., one which will be called by default when you write MyClass someObject;.

这意味着可以不带参数调用构造函数。这使它成为默认构造函数,即,在您编写时默认调用的构造函数MyClass someObject;

The part : m_classID(-1), m_userdata(0)is called initialization list. It is a way to initialize some fields of your object (all of them, if you want) with values of your choice, instead of leaving them as undefined.

该部分 : m_classID(-1), m_userdata(0)称为初始化列表。这是一种使用您选择的值初始化对象的某些字段(如果需要,可以全部使用)的方法,而不是将它们保留为未定义。

After executing the initialization list, the constructor body (which happens to be empty in your example) is executed. Inside it you could do more assignments, but once you have entered it all the fields have already been initialized - either to random, unspecified values, or to the ones you chose in your initialization list. This means the assignments you do in the constructor body will not be initializations, but changes of values.

执行初始化列表后,将执行构造函数体(在您的示例中恰好为空)。在它里面你可以做更多的分配,但是一旦你输入它,所有的字段都已经被初始化——或者是随机的、未指定的值,或者是你在初始化列表中选择的值。这意味着您在构造函数体中所做的赋值不是初始化,而是值的更改。

回答by Asik

It is an initialization list.

它是一个初始化列表。

By the time you get in the body of the constructor, all fields have already been constructed; if they have default constructors, those were already called. Now, if you assign a value to them in the body of the constructor, you are calling the copy assignment operator, which may mean releasing and reacquiring resources (e.g. memory) if the object has any.

当你进入构造函数体时,所有的字段都已经构造好了;如果他们有默认构造函数,那些已经被调用。现在,如果您在构造函数的主体中为它们赋值,则您正在调用复制赋值运算符,这可能意味着释放和重新获取资源(例如内存)(如果对象有的话)。

So in the case of primitive types like int, there's no advantage compared to assigning them in the body of the constructor. In the case of objects that have a constructor, it is a performance optimization because it avoids going through two object initializations instead of one.

因此,对于像 int 这样的原始类型,与在构造函数的主体中分配它们相比,没有任何优势。对于具有构造函数的对象,这是一种性能优化,因为它避免了两次对象初始化而不是一次。

An initialization list is necessary if one of the fields is a reference because a reference can never be null, not even in the brief time between object construction and the body of the constructor. The following raises error C2758: 'MyClass::member_' : must be initialized in constructor base/member initializer list

如果其中一个字段是引用,则初始化列表是必要的,因为引用永远不能为空,即使在对象构造和构造函数体之间的短暂时间内也是如此。以下引发错误 C2758:“MyClass::member_”:必须在构造函数基/成员初始值设定项列表中初始化

class MyClass {
public :
    MyClass(std::string& arg) {
        member_ = arg;
    }
    std::string& member_;
};

The only correct way is:

唯一正确的方法是:

class MyClass {
public :
    MyClass(std::string& arg) 
        : member_(arg) 
    {
    }
    std::string& member_;
};

回答by Dominic Rodger

It denotes the beginning of an initialiser list, which is for initialising member variables of your object.

它表示初始化列表的开始,用于初始化对象的成员变量。

As to: MyClass(m_classID = -1, m_userdata = 0);

至于: MyClass(m_classID = -1, m_userdata = 0);

That declares a constructor which can take arguments (so I could create a MyClassusing MyClass m = MyClass(3, 4), which would result in m_classIDbeing 3, and m_userdatabeing 4). If I were to pass no arguments to the MyClassconstructor, it would result in an equivalent object being created to the version with the initialiser list.

这声明了一个可以接受参数的构造函数(所以我可以创建一个MyClassusing MyClass m = MyClass(3, 4),这将导致m_classID3 和m_userdata4)。如果我不向MyClass构造函数传递任何参数,则会导致为具有初始化列表的版本创建一个等效的对象。

回答by JaredPar

It signals the beginning of an initializer list.

它表示初始化列表的开始。

Also it is not equivalent to MyClass(m_classId=-1,m_userData=0). This is attempting to define a constructor with 2 parameters that have default values. However the values lack types and it should not compile at all.

它也不等同于 MyClass(m_classId=-1,m_userData=0)。这是试图定义一个带有 2 个具有默认值的参数的构造函数。然而,这些值缺少类型,它根本不应该编译。

回答by JohnMcG

That is called the member initialization list. It is used to call the superclass constrctors, and give your member variables an initial value at the time they are created.

这就是所谓的成员初始化列表。它用于调用超类构造函数,并在创建成员变量时为其赋予初始值。

In this case, it is initializing m_classIDto -1 and m_userDatato NULL.

在这种情况下,它初始化m_classID为 -1 和m_userDataNULL。

It is not quite equivalent to assigning in the body of the constructor, because the latter first creates the member variables, then assigns to them. With the initialization, the initial value is provided at the time of creation, so in the case of complex objects, it can be more efficient.

它并不完全等同于在构造函数体中赋值,因为后者首先创建成员变量,然后再赋值给它们。有了初始化,在创建的时候就提供了初始值,所以在对象复杂的情况下,效率会更高。

回答by T.E.D.

It isn't precisely an operator. It's a part of the syntax for a constructor.

它不完全是一个操作员。它是构造函数语法的一部分。

What it is saying is that following it will be a list of member variables and their initial values.

它的意思是,在它之后将是一个成员变量及其初始值的列表。

Constant members have to be initialized this way. Non-constants can be initialized here too, as long as it can be done with a single expression. If it takes more code than that to initialize a member, you have to put actual code between the {}'s to do it.

常量成员必须以这种方式初始化。非常量也可以在这里初始化,只要它可以用单个表达式完成。如果初始化成员需要更多代码,则必须在 {} 之间放置实际代码才能执行此操作。

A lot of people like to put pretty much all their constructor code in the initilizer list. I have one co-worker who regularly writes classes with several screens of initilizers, and then puts "{}" for the constructor code.

很多人喜欢将几乎所有的构造函数代码放在初始化程序列表中。我有一个同事经常用几个屏幕的初始化程序编写类,然后将“{}”放在构造函数代码中。

回答by Patrick

Its the start of an initialiser list which sets member variables during the construction of the object. Your example "MyClass(m_classID = -1, m_userdata = 0);" is not possible as you have not defined the correct constructor and you would not be able to access the member variables in the parameter list anyway... you could have something like:

它是一个初始化列表的开始,它在对象的构造过程中设置成员变量。您的示例“MyClass(m_classID = -1, m_userdata = 0);” 是不可能的,因为您没有定义正确的构造函数,并且无论如何您都无法访问参数列表中的成员变量……您可能有以下内容:

MyClass( int classId = -1, void* userData = 0 ) : m_classID(classId), m_userdata(userData) {}

The initialiser list is considered better than:

初始化列表被认为比:

MyClass( int classId = -1, void* userData = 0 ) {
    m_classID = classId;
    m_userdata = userData;
}

Google for more info.

谷歌了解更多信息。

回答by Marcin Deptu?a

It's a initialization list. In your example, it's rather something like this (something like this - doesn't mean it's equivalent in all cases):

这是一个初始化列表。在你的例子中,它是这样的(像这样 - 并不意味着它在所有情况下都是等价的):


class MyClass {

public:

    MyClass(){
         m_classID = -1;
         m_userdata = 0;
    }

    int m_classID;
    void *m_userdata;

};

回答by SebastianK

In this case: Yes, ist is equivalent because only primitive types are concerned.

在这种情况下:是的,ist 是等效的,因为只涉及原始类型。

If the members are classes (structs) then you should prefer the initialization list. This is because otherwise the objects are default constructed and then assigned.

如果成员是类(结构),那么您应该更喜欢初始化列表。这是因为否则对象是默认构造然后分配的。