Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the conditional operator (?:) work in C++?

Tags:

c++

I have written the code snippet below:

#include <string>

int main() {
    std::string str = "test";
    (str == "tes") ? str.replace(0, 1, "T") : 0;
}

(See here)

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?

like image 995
G.yang Avatar asked Dec 19 '17 03:12

G.yang


People also ask

How does a conditional operator work?

The conditional operator works as follows: The first operand is implicitly converted to bool . It is evaluated and all side effects are completed before continuing. If the first operand evaluates to true (1), the second operand is evaluated.

What is condition operator in C give example?

Example: C Ternary Operatorage >= 18 - test condition that checks if input value is greater or equal to 18. printf("You can vote") - expression1 that is executed if condition is true. printf("You cannot vote") - expression2 that is executed if condition is false.

What is conditional statement in C with example?

Conditional Statements in C programming are used to make decisions based on the conditions. Conditional statements execute sequentially when there is no condition around the statements. If you put some condition for a block of statements, the execution flow may change based on the result evaluated by the condition.

How conditional or ternary operator works in C?

The ternary operator take three arguments: The first is a comparison argument. The second is the result upon a true comparison. The third is the result upon a false comparison.


1 Answers

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:

  1. Both the true case and the false case must be the same type (or be convertible to the same type).
  2. It still works even if the type does not have a default constructor (so it's more elaborate than the above).

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.

like image 156
Alexander Huszagh Avatar answered Oct 04 '22 02:10

Alexander Huszagh