Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

c++ - Class construction with initial values

I'm new to C++, and the whole idea of classes - I'm still reading a book to try and learn. The book I'm reading says that when I construct a class, I can assign default values by doing this:

class foo {
public:
   foo(char c, int i);
private:
   char exampleChar;
   int exampleInt;
};

foo::foo(char c, int i):
exampleChar(c),
exampleInt(i)
{}

This code (to me) looks very messy, and doesn't follow rules that I'm used to in other languages. My question is, what's the difference between doing the above, and this (below, which I personally think looks a lot cleaner)?

foo::foo(char c, int i) {
   exampleChar = c;
   exampleInt = i;
}

Sort of things I'm thinking about are: are there performance/efficiency issues if done on a large scale - or is it exactly the same?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The first way, by doing : exampleChar(c), exampleInt(i) is called an initializer list.

If you do it the second way, the two variables are default constructed first1, then you assign them a value. (When the actual body of the constructor is entered, anything that hasn't been initialized by the initializer list is default constructed.) This is a waste of time because you're just overwriting the values anyway. For small types like int or char this isn't a big deal, but when those member variables are large types that would take lots of cycles to construct, you definitely want to use the initializer list.

The second way won't waste time giving them a default value and then overwriting it - it will set their values directly to that value you give it (or call the right constructor if the member is an object).

You can see what we mean by doing this:

class MyClass {
public:
    int _i; // our data

    // default constructor
    MyClass() : _i(0) { cout << "default constructor"; }

    // constructor that takes an int
    MyClass(int i) : _i(i) { cout << "int constructor"; }

    // assignment operator
    void operator=(int i) { _i = i; cout << "assignment operator"; }
};

class OtherClass {
public:
    MyClass c;

    OtherClass() {
        c = 54;
    }
};

OtherClass oc;

You'll see that

default constructor
assignment operator

is printed. That's two function calls which, for other classes, could be expensive.

If you change the constructor of OtherClass to

OtherClass() : c(54) {   }

You'll see that

int constructor

is printed. Just one call compared to two. This is the most efficient way.

Initializer lists are also a must when you

  1. have types that have no default constructor. You have to call the right constructor in the initializer list.

  2. have a const member that you want to give some value (rather than just have permantently the default value

  3. have a reference member. You must use initializer lists on these.

tl;dr: do it because it's at least as fast but never slower than the other way, and sometimes far faster.

1 For built in types like int and char, they are actually not constructed at all; they just have the value of whatever memory they happen to have had previously.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...