为什么 std::max 不适用于字符串文字?

Why is std::max not working for string literals?

我试图找到两个字符串的最大值,它在第一种情况下(传递 std::string 变量时)给出了正确答案,但在第二种情况下(传递直接字符串时)给出了错误).

#include<bits/stdc++.h>
using namespace std;

int main()
{
    // Case 1
    string str1 = "abc", str2 = "abcd";
    cout << max(str1, str2) << endl;

    // Case 2
    cout << max("abc", "abcd") << endl;
}

在你的第二种情况下,

std::cout << std::max("abc", "abcd") << std::endl;

它们是字符串文字,其中 "abc" 的类型为 char const [4]"abcd" 的类型为 char const [5].

因此,在函数调用std::max("abc", "abcd")中,std::max必须推导

auto max(char const (&a)[4], char const (&b)[5]) {
    return a < b ? b : a;
}

这是不可能的,因为 std::max 没有函数模板重载,它采用不同的类型作为模板参数。因此,错误!


警告!

如果您在 std::max 中明确提及模板类型 const char*,则可能已被编译。这是因为,对于 "abc""abcd",由于 C++ 中数组到指针的衰减,类型也可以是 const char*s。

 std::cout << std::max<const char*>("abc", "abcd" ) << '\n';  // compiles
                      ^^^^^^^^^^^^^

另外,std::maxstd::initializer_list重载,反过来会推导出上面也const char*作为模板类型:

std::cout << std::max({ "abc", "abcd" }) << '\n';   // compiles

但是,你不应该这样做 !

作为 @AlanBirtles pointed out, this can cause the undefined behavior, due to the fact that the std::max will compare the pointers of the two different arrays. The result can not be relayed and should be doing the above. Use the std::string for comparison as in your first case. Using string literals (C++14 起),你可以做一个最小的改变,使第二种情况与第一种情况相同:

#include <string>
using namespace std::string_literals;

std::cout << std::max("abc"s, "abcd"s) << '\n';

作为旁注,请参阅以下内容:

  • Why is "using namespace std;" considered bad practice?

区别在于类型。

典型的 max 实现可能如下所示:

template <typename T>
auto max(const T &a, const T &b) {
    return a < b ? b : a;       
}

当您对 std::string 使用 max 时,< 符号实际上已过载。 std::string::operator<() 方法用于比较字符串。

当您为 const char * 使用最大值时。 < 只比较指针而不考虑字符串的内容。