As your unasked question "How do I fix it?" was answered by Yuki without any details I will provide an answer "What happend there?".
In C++ object is constructed from base class. So the order is following:
A::A(int); // base class constructor
B::B(); // inherited class constructor
All member objects are initialized in initializer list:
B::B()
: // Initializer list begin.
A(), // Base class initialized first.
m_aStuff() // Members of current class are initialized next.
{ // End of initializer list.
// All members are safe to use.
}
This is the order of object initialization. As you can see here the member m_aStuff
initialized after base constructor A::A(int)
.
Constructor is a member function and as every function requires arguments to be evaluated. So the function int B::filter()
is called before object is initialized. Which means that member variables are not initialized either. In other words the order of execution is:
- Call
B::filter()
- Modify member variable
B::m_aStuff
- Call base class constructor
A::A(int)
- Initialize member variable
B::m_aStuff
Obviously step 2 is modifying variable before it was initialized. Depending on implementation of std::map
this can cause different behavior (probably undefined).
In fact following two constructions are equal:
B::B() :
A(0)
{}
and
B::B() :
A(0),
m_aStuff()
{}
but in the second case you are initializing it explicitly, while in first case compiler will generate this code for you.
Your solution new(&m_aStuff)std::map<int,int>;
initializes object before using it which makes behavior more defined. But next the generated constructor of class B
will kick in and B::m_aStuff
will be initialized once again. This will set your map to initial state (though I can imagine scenarios in which memory will leak).