开发者

What is the advantage of using initializers for a constructor in C++?

开发者 https://www.devze.com 2022-12-13 01:56 出处:网络
Sphere() : theRadius(1.0) { } Why is it preferable to have a constructor written with initializers (above) than a constructor that initializes the开发者_运维百科 data members within its body (below)
Sphere() : theRadius(1.0)
{
}

Why is it preferable to have a constructor written with initializers (above) than a constructor that initializes the开发者_运维百科 data members within its body (below)?

Sphere()
{
     theRadius = 1.0;
}


All members are initialised before entering the body of the constructor. If you don't provide an initialiser in the init list, then they're default constructed.

In your first example the following happens:

  • theRadius is initialised to 1.0

In your second example the following happens:

  • theRadius is initialised
  • 1.0 is copied to theRadius

With simple types like ints and floats this won't matter much. however if your members are objects with non-trivial constructors / copy constructors then it's a lot more efficient to use the initialisation list approach.


If you don't initialize fields explicitly, the compiler will try to run the default constructor of them. If they don't have an accessible default constructor, your source code will fail to compile:

class Field {
public:
    Field(int x) {}
};
class Test {
    Field f;
public: 
    Test() {  // compiler error here. `Field` doesn't have default constructor.
       f = Field(10); 
    } 
};
int main ( ) {
    Test t;
}

If they do have a default constructor, you're calling it unnecessarily as you're calling another constructor of the field in the body.


A constructor is always called for object attributes before entering the constructor's body. If you don't specify a constructor yourself, the default one will be called, and operator= will be used later to change the value.

This may not be what you want. In particular, you can't change the value of a const attribute inside the constructor body. You have to use the init list.


Because otherwise the objects default constructor is called and then the value is set.

This would call only the string constructor

class Foo{
     std::string s;
     Foo() : s("Hello World"){}
}

Where as this:

class Foo{
     std::string s;
     Foo(){
         s = "Hello World";
     }
}

Would call the default string constructor and then set the value of the string to "Hello World"


As already said, for non-primitive types it makes a difference.

It's also the only way to initialise const member variables.

class MyClass
{
 const int x;
public: 
 MyClass(int x)
 {
  this->x=x;
 }
};

This should not compile.


Like others have said, it's more efficient to use the first form for types with non-trivial construction.

In addition, the first form gives you the ability to catch any exceptions thrown in the constructor of the member object (or base class) that is being initialized by using the function form of a try/catch block. e.g:

MyObject() : memberObject(...)
try {
  // my constructor
}
catch (...) {
  // catches exceptions in try block AND memberObject constructor
}

That's not missing a set of brackets. If you do put another set of brackets around the try/catch block it will not catch exceptions in the memberObject constructor, just the try block.


It is mainly used to initialize constants and reference variable since they can't be initialized in body of constructor.

0

精彩评论

暂无评论...
验证码 换一张
取 消