What does a colon following a C++ constructor name

2019-01-02 19:49发布

This question already has an answer here:

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

class MyClass {
public:

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

    int m_classID;
    void *m_userdata;
};

9条回答
时光乱了年华
2楼-- · 2019-01-02 20:14

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;

};
查看更多
笑指拈花
3楼-- · 2019-01-02 20:18

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.

查看更多
孤独总比滥情好
4楼-- · 2019-01-02 20:22

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.

查看更多
皆成旧梦
5楼-- · 2019-01-02 20:23

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;.

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.

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.

查看更多
旧时光的记忆
6楼-- · 2019-01-02 20:23

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( 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.

查看更多
姐姐魅力值爆表
7楼-- · 2019-01-02 20:25

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.

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

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_;
};
查看更多
登录 后发表回答