为什么 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::max
的std::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 *
使用最大值时。 <
只比较指针而不考虑字符串的内容。
我试图找到两个字符串的最大值,它在第一种情况下(传递 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::max
的std::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 *
使用最大值时。 <
只比较指针而不考虑字符串的内容。