Search code examples
c++performancec++11constructordelegating-constructor

Do C++11 delegated ctors perform worse than C++03 ctors calling init functions?


[this question has been highly edited; pardon that, I've moved the edits into an answer below]

From Wikipedia (subarticle included) on C++11:

This [new delegating constructors feature] comes with a caveat: C++03 considers an object to be constructed when its constructor finishes executing, but C++11 considers an object constructed once any constructor finishes execution. Since multiple constructors will be allowed to execute, this will mean that each delegating constructor will be executing on a fully constructed object of its own type. Derived class constructors will execute after all delegation in their base classes is complete."

Does this mean that delegation chains construct a unique temporary object for every link in a ctor delegation chain? That kind of overhead just to avoid a simple init function definition would not be worth the additional overhead.

Disclaimer: I asked this question, because I'm a student, but the answers thus far have all been incorrect and demonstrate a lack of research and/or understanding of the research referenced. I've been somewhat frustrated by this, and as a result my edits and comments have been hastily and poorly composed, mostly over smart phone. Please excuse this; I hope I've minimized that in my answer below, and I have learned that I need to be careful, complete, and clear in my comments.


Solution

  • The overhead is measurable. I implemented the following main-function with the Player-class and ran it several times with the delegating constructor as well as with the constructor with the init function (commented out). I built the code with g++ 7.5.0 and different optimization levels.

    Build command: g++ -Ox main.cpp -s -o file_g++_Ox_(init|delegating).out

    I ran every program five times and calculated the average on a Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz

    Runtimes in msec:

    Opt-Level | delegating | init

    -O0 | 40966 | 26855

    -O2 | 21868 | 10965

    -O3 | 6475 | 5242

    -Ofast | 6272 | 5123

    To construct 50,000! objects is probably not a usual case, but there is a overhead for delegation constructors and that was the question.

    #include <chrono>
    
    class Player
    {
    private:
        std::string name;
        int health;
        int xp;
    public:
        Player();
        Player(std::string name_val, int health_val, int xp_val);
    };
    
    Player::Player()
        :Player("None", 0,0){
    }
    
    //Player::Player()
    //        :name{"None"}, health{0},xp{0}{
    //}
    
    Player::Player(std::string name_val, int health_val, int xp_val)
        :name{name_val}, health{health_val},xp{xp_val}{
    
    }
    
    int main() {
        auto start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < 50000; i++){
            Player player[i];
        }
    
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( end - start ).count();
    
        std::cout << duration;
    
        return 0;
    }