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

Yuv*_*har 5 c++ algorithm std max stdstring

我试图找到两个字符串的最大值,它在第一种情况下(传递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;
}
Run Code Online (Sandbox Code Playgroud)

JeJ*_*eJo 10

在你的第二种情况下,

std::cout << std::max("abc", "abcd") << std::endl;
Run Code Online (Sandbox Code Playgroud)

它们是字符串文字,其中"abc"has typechar const [4]"abcd"has type char const [5]

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

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

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


警告!

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

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

此外, ,std::initializer_list的重载std::max反过来也会将上面的内容推导const char*为模板类型:

std::cout << std::max({ "abc", "abcd" }) << '\n';   // compiles
Run Code Online (Sandbox Code Playgroud)

但是,您不应该这样做

正如@AlanBirtles指出的,这可能会导致未定义的行为,因为它将std::max比较两个不同数组的指针。结果无法转发,应该执行上述操作。std::string像第一种情况一样使用 进行比较。使用字符串文字(C++14 起),您可以进行最小的更改,并使第二种情况与第一种情况相同:

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

std::cout << std::max("abc"s, "abcd"s) << '\n';
Run Code Online (Sandbox Code Playgroud)

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

  • 虽然“const char*”变体可能会编译比较来自两个单独数组的指针具有未定义的行为,但它也可能只返回第二个存储在内存中的文字,这不太可能是OP想要的,而且肯定不一样行为与“std::string”相同 (5认同)