0

I consider this SO question as a general point of view regarding the initialization and it answers already a lot:

Should constructor initialize all the data members of the class?

But, I didn't find really anything regarding a possible performance issue when for example my class has 100 members and I initialize each member with the {} command, just because Eclipse is warning me about uninitialized member:

Member 'foo' was not initialized in this constructor

My question: Can an initialization of each member in a class with lot of members [>50] lead to a performance issue each time this class is instantiated?

Update: Due to the first comments: I am asking in general. Eclipse is warning me in my project 9 times split over 4 classes!

Peter VARGA
  • 4,780
  • 3
  • 39
  • 75

1 Answers1

-1

Here my results running it with gcc.

I tested it [5-times and took the average] with different count of class members but with 100'000'000 instantiation of the class.

It was a bit tricky because I used the highest optimization level -O3 and therefore I had to avoid the compiler optimizes code away.

With 100 class members:

Initialized class members:      4'484 msec
Not initialized class members:     50 msec

With 25 class members:

Initialized class members:      1'146 msec
Not initialized class members:     50 msec // as expected it didn't change

With 500 class members:

Initialized class members:     22'129 msec
Not initialized class members:     50 msec // as expected it didn't change

My conclusion is:

There is - under normal circumstances - no remarkable performance issue when all class members are initialized. With under normal circumstances I mean that when there is a function [with other code] with 100'000'000 iterations that the member initialization really doesn't count.

As stated in the comments a good design shouldn't have so many class members - I was just general curious.


PS:

I checked the assembler listing and - of course - indeed in the initialized version gcc initialized each int member with movq $0, 40(%rsp) - the 40 is the position on the stack.


#include <stdlib.h>
#include <stdio.h>
#include <chrono>
#include <ctime>
#include <utility>

template<typename TimeT = std::chrono::microseconds>
class measure
{
public:
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F func, Args&&... args)
    {
        auto start = std::chrono::system_clock::now();
        func(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                                (std::chrono::system_clock::now() - start);

        return duration.count();
    }
};

class foo
{
   // for uninitialized version remove the {}
   size_t mainValue {};
   size_t classMember0 {};
   ...
   size_t classMember499 {};

public:
    foo( size_t value ) : mainValue (value + 4660) {};
    auto getMainValue() -> size_t { return mainValue; };
};

auto runCode( size_t iterationCount ) -> void
{
    size_t someValue {};
    for ( size_t j = 0 ; j < iterationCount ; ++j )
    {
        foo MyFoo (iterationCount);
        someValue += MyFoo.getMainValue();
    }
    printf( "Result=%ld\n", someValue );   // that the whole code isn't optimized away...
}

int main( int argc, char * argv [] )
{
    if ( argc != 2 )
    {
        printf( "Usage: %s <Start-Value>\n", argv [0] );
        return 0;
    }

    size_t variableValue = (size_t) atof( argv [1] );
    auto threadExecutionTime = measure<>::execution( [&] () { runCode( variableValue ); } );

    printf( "Total execution time was %.3f milliseconds. %s",
                threadExecutionTime / 1000. );
}
Peter VARGA
  • 4,780
  • 3
  • 39
  • 75
  • just as a sidenote: in general I am quite picky about "give credits to whom credit due", but in this case I feel your answer would be fine without refering to my comments. Sometimes my comments are just blatantly off. In particular I am not even sure if I 100% agree myself with the statement you quote ;) – 463035818_is_not_an_ai Feb 20 '18 at 08:00