Reputation: 357
I have written the code snippet below:
#include <string>
int main() {
std::string str = "test";
(str == "tes") ? str.replace(0, 1, "T") : 0;
}
Unfortunately, it causes a logic_error
:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct NULL not valid
I want to know the reason why the compiler constructs a string object?
Upvotes: 12
Views: 1001
Reputation: 8018
so,i want to know the reason why the compiler construct a string object?
Because std::string
provides an implicit constructor that takes a plain const char*
expecting a NUL
terminated c-style string.
There's a runtime assertion that there's no nullptr
(== 0
) passed with that constructor, hence the exception you see.
As a side note:
Your statement
(str == "tes") ? str.replace(0, 1, "T") : 0;
might be optimized out by a decent compiler, because it doesn't have any significant side effects.
So that exception you see might go away with builds using a different optimization level.
Upvotes: 0
Reputation: 14614
The ternary operator effectively works like follows:
std::string str = "test";
std::string _; // using _ since you don't store the variable
if (str == "tes") {
_ = str.replace(0, 1, "T");
} else {
_ = 0; // this calls std::string(nullptr);
}
In the case above, you don't store the value, but a few conditions must be noted:
The issue here is that your code expects the type to be std::string
, based on the type in the true-case. The type in the false-case is a literal, a literal that can be considered equivalent to NULL
, and therefore can be considered a const char*
which is convertible to std::string
. If you try to construct a std::string
from a nullptr, it throws the above exception.
This is actually quite subtle, since if you use any integer literal other than 0, the compiler will throw an error:
#include <string>
int main()
{
std::string s(0); // 0 is comparable to NULL
// std::string s1(1); // compiler error: no constructor found
return 0;
}
Be careful with implicit conversions. The null check and runtime error is quite graceful, and saved you from subtle errors or crashes (almost certainly a segfault) later on.
Upvotes: 17