Colon use in function call


I need to understand the purpose of the colon in the below function call.


DigitList (unsigned d, DigitList* prv = 0, DigitList* nxt = 0)
: data(d), prev(prv), next(nxt)
{}

This function call is part of the below struct.

struct DigitList
{
int data;
DigitList* prev;
DigitList* next;

DigitList (unsigned d, DigitList* prv = 0, DigitList* nxt = 0)
: data(d), prev(prv), next(nxt)
{}
};

Thanks in advance!
That's not a function call, that's a constructor definition.
It means that the constructor for data is to be passed d. The same for prev and next.
In this case, this is kind of a stupid way to write it, since all these are integral value and don't have constructors. It can be rewritten (in this case!) as
1
2
3
4
5
DigitList (unsigned d, DigitList* prv = 0, DigitList* nxt = 0){
    this->data=d;
    this->prev=prv;
    this->next=nxt;
}
I see now - Thank you!
Curt, the syntax you are referring to is called an initializer list. It is a special syntax limited to use in constructors. Its purpose is to initialize the data members of the struct/class.

Although in some cases there is no benefit to using initializer lists, you should get into the habit of always using them since there is never a disadvantage to them.

To understand why initializer lists are important, consider the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MyClass {
  public:
     MyClass( const std::string& s1, const std::string s2 );
  private:
     std::string  string1;
     std::string  string2;
};

// Consider this implementation:
MyClass::MyClass( const std::string& s1, const std::string& s2 ) :
    string1( s1 ), string2( s2 )
{
}

// versus this one:
MyClass::MyClass( const std::string& s1, const std::string& s2 )
{
   string1 = s1;
   string2 = s2;
}


int main() {
   MyClass c( "hello", "world" );
}


Consider the second implementation above (member-wise assignment).
The compiler does not know you are going to initialize each member of MyClass, so before it runs your constructor's code, it runs the default constructor for each member of MyClass.

So to run the second implementation above, four function calls are needed:
1. std::string default constructor is called to default construct string1;
2. std::string default constructor is called to default construct string2;
3. std::string assignment operator is called to assign s1 to string1;
4. std::string assignment operator is called to assign s2 to string2.

In the first implementation above, by using an initializer list, you are telling the compiler that instead of calling the default constructor for string1 and string2 it can instead call the copy constructor, which means only two function calls instead of four.

For POD (plain 'ol data) types such as int, float, char, and all raw pointer types, the default constructor does nothing and the compiler doesn't even bother generating a function call. Which is why helios said not to bother with initializer lists in your case.

But there is never a disadvantage to using initialiizer lists so I would highly recommend that you learn how to use initializer lists and ALWAYS use them in your constructors.
Topic archived. No new replies allowed.