Reputation: 19302
The following code crashes, raising std::bad_alloc
or sometimes std::logic_error
.
#include <string>
class Crasher {
public:
Crasher() : value(default_value) {}
private:
std::string value;
const std::string default_value = "default is yours";
};
int main(void) {
Crasher();
}
I believe the reason is that the members are initialized out of order, and when value
is being intialized in initializer list, default_value
hasn't yet been initialized.
However, I don't get any compiler warnings or errors with -Wall
enabled. However if I change value
and default_value
to a POD type like int
, then I get a warning from g++
:
$ g++ -Wall crasher.cpp
crasher2.cpp: In constructor ‘Crasher::Crasher()’:
crasher2.cpp:5:23: warning: ‘*<unknown>.Crasher::default_value’ is used uninitialized in this function [-Wuninitialized]
5 | Crasher() : value(default_value) {}
|
Why do I not get a warning when the type is std::string
? Is this a compiler problem, or a quirk of the language?
Upvotes: 5
Views: 116
Reputation: 39868
Initializing one int
from another performs an lvalue-to-rvalue conversion on the source. If that’s uninitialized, the behavior is undefined. Initializing one object of class type from another does not do so—it calls a constructor, which merely binds a reference to the source. That’s not undefined even if the source is out of lifetime, although typical copy constructors will of course exhibit undefined behavior in that case. Whether you get a warning then depends on what analysis the compiler does after any inlining of the constructor. With the default of no optimization, getting no warning is understandable.
Upvotes: 2