Optimization due to constructor initializer list

后端 未结 8 1762
故里飘歌
故里飘歌 2020-12-13 21:23

Constructors should initialize all its member objects through initializer list if possible. It is more efficient than building the constructors via assign

相关标签:
8条回答
  • 2020-12-13 22:06

    Suppose you have a data member in your class which is std::string type. When the constructor of this class is executed, the default constructor string class would be called automatically because objects are initialized before the body of the constructor.

    If you are assigning the string inside the body of the constructor, then a temporary object would be created and given to the string's assignment operator. The temporary object will be destroyed at the end of the assignment statement. If you do this in the initializer list, a temporary object will not be created.

    class Person
    {
    public:
        Person(string s);
        ~Person();
    private:
        string name;
    };
    
    
    // case 1
    Person::Person(string s)
    {
       name = s;   // creates a temporary object
    }
    
    // case 2
    Person::Person(string s):name(s) {} // whereas this will not create a temporary object.
    
    0 讨论(0)
  • 2020-12-13 22:09

    From the C++FAQ :

    Consider the following constructor that initializes member object x_ using an initialization list: Fred::Fred() : x_(whatever) { }. The most common benefit of doing this is improved performance. For example, if the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object. Even if the types are not the same, the compiler is usually able to do a better job with initialization lists than with assignments.

    The other (inefficient) way to build constructors is via assignment, such as: Fred::Fred() { x_ = whatever; }. In this case the expression whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object's assignment operator. Then that temporary object is destructed at the ;. That's inefficient.

    As if that wasn't bad enough, there's another source of inefficiency when using assignment in a constructor: the member object will get fully constructed by its default constructor, and this might, for example, allocate some default amount of memory or open some default file. All this work could be for naught if the whatever expression and/or assignment operator causes the object to close that file and/or release that memory (e.g., if the default constructor didn't allocate a large enough pool of memory or if it opened the wrong file).

    0 讨论(0)
  • 2020-12-13 22:09

    because if you are using the inizializer list what you are calling is the constructor copy of that object .

    While if you initialize objects inside the constructor body you are doing an assignment.

    example: here i m calling the copy constructor of int.

    
      myClass::myClass( int x ) : member(x) {}
    

    while here i m calling the operator=(const int& ). the asignment

    
        myClass::myClass( int x )
        {
             member = x;
        }
    

    usually the asignment does more operation then a simple copy. you must keep in account also temporary object!

    0 讨论(0)
  • 2020-12-13 22:11

    To prevent double initialization.

    class B
    {
    //whatever
    };
    
    class A
    {
       B _b;
    public:
       A(B& b)
    };
    

    Now the two cases:

    //only initializes _b once via a copy constructor
    A::A(B& b) : _b(b)
    {
    }
    
    //initializes _b once before the constructor body, and then copies the new value
    A::A(B& b)
    {
       //_b is already initialized here
       //....
       //one extra instruction:
       _b = b;
    }
    
    0 讨论(0)
  • 2020-12-13 22:13

    Consider this program:

    #include <iostream>
    
    struct A {
      A() { std::cout << "A::A()\n"; }
      A(int) { std::cout << "A::(int)\n"; }
      void operator=(const A&) { std::cout << "A::operator=(const A&)\n"; }
    };
    
    struct C1 {
      A a;
      C1(int i) { 
        a = i;
      }
    };
    
    struct C2 {
      A a;
      C2(int i)  : a(i) {}
    };
    
    int main() {
      std::cout << "How expesive is it to create a C1?\n";
      { C1 c1(7); }
      std::cout << "How expensive is it to create a C2?\n";
      { C2 c2(7); }
    }
    

    On my system (Ubuntu 11.10, g++ 4.6.1), the program produces this output:

    How expesive is it to create a C1?
    A::A()
    A::(int)
    A::operator=(const A&)
    How expensive is it to create a C2?
    A::(int)
    

    Now, consider why it is doing that. In the first case, C1::C1(int), a must be default-constructed before C1's constructor can be invoked. Then it is must assigned to via operator=. In my trivial example, there is no int assignment operator available, so we have to construct an A out of an int. Thus, the cost of not using an initializer is: one default constructor, one int constructor, and one assignment operator.

    In the second case, C2::C2(int), only the int constructor is invoked. Whatever the cost of a default A constructor might be, clearly the cost of C2:C2(int) is not greater than the cost of C1::C1(int).


    Or, consider this alternative. Suppose that we add the following member to A:

    void operator=(int) { std::cout << "A::operator=(int)\n"; }
    

    Then the output would read:

    How expesive is it to create a C1?
    A::A()
    A::operator=(int)
    How expensive is it to create a C2?
    A::(int)
    

    Now is is impossible to say generally which form is more efficient. In your specific class, is the cost of a default constructor plus the cost of an assignment more expensive than a non-default constructor? If so, then the initialization list is more efficient. Otherwise it isn't.

    Most classes that I've ever written would be more efficiently initialized in an init list. But, that is a rule-of-thumb, and may not be true for every possible case.

    0 讨论(0)
  • 2020-12-13 22:16

    Because it initialises directly, instead of default initialising and then assigning. It likely won't matter performance-wise for PODs, but it will if the type constructor is doing heavy-weight work.

    Also, in some cases you must use init list, so you should always do it for consistency.

    0 讨论(0)
提交回复
热议问题