c++stringoperatorstemporarychararray

Temporary string comparison with > and < operators in C++


These operators do not perform lexicographical comparisons and seem to provide inconsistent results.

#include <iostream>
int main () {
    std::cout << ("70" < "60") << '\n';
    std::cout << ("60" < "70") << '\n';
    return 0;
}

and

#include <iostream>
int main() {
    std::cout << ("60" < "70") << '\n';
    std::cout << ("70" < "60") << '\n';
    return 0;
}

both print

1
0

The same holds true for std::less<>(). However, std::less<std::string>() provides the correct lexicographical comparison. What is the reason for this behaviour? Are the comparisons shown above comparing the addresses of char arrays?


Solution

  • Character literals are character arrays. You are comparing these arrays, which after array-to-pointer decay means you are comparing the addresses of the first byte of these arrays.

    Each character literal may refer to a different such array, even if it has the same value. And there is no guarantee about the order of their addresses.

    So any possible outcome for your tests is allowed. 0/0 as well as 0/1, 1/0 and 1/1.


    You can avoid all the C-style array behavior of string literals by always using std::string or std::string_view literals instead:

    #include <iostream>
    
    using namespace std::string_literals;
    
    int main () {
        std::cout << ("70"s < "60"s) << '\n';
        std::cout << ("60"s < "70"s) << '\n';
        return 0;
    }
    

    This uses the user-defined string literal operator""s from the standard library to immediately form std::strings from the string literals. sv can be used for std::string_views instead. (string_view will incur less performance cost, in particular no dynamic allocation.)