In this particular case, is there a difference between using a list of member initializers and assigning values ​​in the constructor?

Internally and about the generated code, is there really a difference between:

MyClass::MyClass(): _capacity(15), _data(NULL), _len(0) { } 

and

 MyClass::MyClass() { _capacity=15; _data=NULL; _len=0 } 

thank...

+88
c ++ initialization initialization-list
Jan 03 2018-11-11T00:
source share
11 answers

Assuming these values ​​are primitive types, then no, there is no difference. Initialization lists only matter when you have objects as members, because instead of the default initialization followed by the assignment, the initialization list allows you to initialize the object to its final value. It can be noticeably faster.

+59
Jan 03 2018-11-11T00:
source share

You need to use the initialization list to initialize persistent members, references, and the base class

When you need to initialize constant elements, links, and transfer parameters for base class constructors, as indicated in the comments, you need to use the initialization list.

 struct aa { int i; const int ci; // constant member aa() : i(0) {} // will fail, constant member not initialized }; struct aa { int i; const int ci; aa() : i(0) { ci = 3;} // will fail, ci is constant }; struct aa { int i; const int ci; aa() : i(0), ci(3) {} // works }; 

An example (not exhaustive) class / struct contains a link:

 struct bb {}; struct aa { bb& rb; aa(bb& b ) : rb(b) {} }; // usage: bb b; aa a(b); 

And an example of initializing a base class for which a parameter is required (for example, the default constructor):

 struct bb {}; struct dd { char c; dd(char x) : c(x) {} }; struct aa : dd { bb& rb; aa(bb& b ) : dd('a'), rb(b) {} }; 
+77
Jan 03 '11 at 23:12
source share

Yes. In the first case, you can declare _capacity , _data and _len as constants:

 class MyClass { private: const int _capacity; const void *_data; const int _len; // ... }; 

This would be important if you want to ensure the const -ness of these instance variables when calculating their values ​​at runtime, for example:

 MyClass::MyClass() : _capacity(someMethod()), _data(someOtherMethod()), _len(yetAnotherMethod()) { } 

const instances must be initialized in the list of initializers, or base types must provide publicly accessible constructors without parameters (which primitive types do).

+18
Jan 03 2018-11-11T00:
source share

I think this link http://www.cplusplus.com/forum/articles/17820/ gives an excellent explanation - especially for those who are not familiar with C ++.

The reason that intialiser lists are more efficient is because only assignments are performed inside the constructor body, not initialization. Therefore, if you are dealing with a non-line type, the default constructor for this object is already called before the constructor body has been introduced. Inside the constructor body, you assign a value to this object.

This is essentially a call to the default constructor, followed by a call to the copy assignment operator. The initialization list allows you to directly call the copy constructor, and sometimes it can be much faster (recall that the initializer list is in front of the constructor body)

+6
Mar 16 '13 at 9:08
source share

I will add that if you have class type members without a default constructor, initialization is the only way to build your class.

+5
Jan 03 '11 at 23:11
source share

The big difference is that the assignment can initialize the elements of the parent class; the initializer only works with members declared in the current class.

+3
Jan 03 '11 at 23:10
source share

Depends on the respective types. The difference is similar between

 std::string a; a = "hai"; 

and

 std::string a("hai"); 

where the second form is an initialization list, that is, it matters if the type requires constructor arguments or is more efficient with constructor arguments.

+2
Jan 03 '11 at 23:10
source share

The real difference comes down to how the gcc compiler generates machine code and lays down memory. Explain:

  • (phase1) Before the init body (including the initialization list): the compiler allocates the required memory for the class. The class is already alive!
  • (phase2) In the init element: since memory is allocated, each assignment now indicates an operation with an already exiting / initialized variable.

There are, of course, other ways to handle const elements. But to make their life easier, the compilers of the gcc compiler decided to set some rules.

  • Elements of type const must be initialized before the init body.
  • After phase 1, any write operation is valid only for non-constant members.
+1
Jan 04 2018-11-11T00:
source share

There is only one way to initialize base class instances and non-static member variables and use a list of initializers.

If you do not specify a base or non-stationary member variable in the constructor initializer list, then this element or base will either be initialized by default (if the member / base is a non-POD class class or a non-POD array) or is left uninitialized otherwise.

After entering the constructor body, all bases or elements will be initialized or left uninitialized (i.e. they will have an undefined value). There is no way in the constructor to influence how they should be initialized.

You may be able to assign new values ​​to the members in the constructor body, but it is not possible to assign const members or members of a class type that were made incoherent, and it is impossible to double-check the links.

For built-in types and some custom types, assignment in the constructor body can have the same effect as initialization with the same value in the list of initializers.

If you cannot name a member or base in the list of initializers, and this object is a reference, has a class type without an accessible default constructor declared by the user, const qualified and has a POD type or a POD class type or an array of a POD class containing const qualified member ( directly or indirectly), then the program is poorly formed.

+1
Jan 04 2018-11-11T00: 00Z
source share

If you write a list of initializers, you do everything in one step; if you are not writing a list of initializers, you will take 2 steps: one for declaring and one for assigning a value.

0
Jan 13 2018-12-12T00:
source share

In the constructor, there is a difference between an initialization list and initialization. Consider the code below:

 #include <initializer_list> #include <iostream> #include <algorithm> #include <numeric> class MyBase { public: MyBase() { std::cout << __FUNCTION__ << std::endl; } }; class MyClass : public MyBase { public: MyClass::MyClass() : _capacity( 15 ), _data( NULL ), _len( 0 ) { std::cout << __FUNCTION__ << std::endl; } private: int _capacity; int* _data; int _len; }; class MyClass2 : public MyBase { public: MyClass2::MyClass2() { std::cout << __FUNCTION__ << std::endl; _capacity = 15; _data = NULL; _len = 0; } private: int _capacity; int* _data; int _len; }; int main() { MyClass c; MyClass2 d; return 0; } 

When MyClass is used, all members will be initialized before the first statement in the constructor is executed.

But, when MyClass2 is used, all members are not initialized when the first statement in the constructor is executed.

In a later case, a regression problem may occur when someone adds some code to the constructor before a specific member is initialized.

0
Mar 18 '16 at 10:28
source share



All Articles