在第一种情况下,代码返回-1
#include <iostream>
template <typename T>
int compare( const T &val1, const T &val2){
if(val1 < val2) return -1;
if(val2 < val1) return 1;
return 0;
}
int main(){
std::string v1= "hello", v2 = "world";
std::cout << compare("hello", "world") << std::endl;
}
在第二种情况下,即使方法调用没有变化,代码也返回1。
#include <iostream>
template <typename T>
int compare( const T &val1, const T &val2){
if(val1 < val2) return -1;
if(val2 < val1) return 1;
return 0;
}
int main(){
std::cout << compare("hello", "world") << std::endl;
}
我正在使用g ++ 7.4.0。
答案 0 :(得分:1)
在两种情况下,推论T
为char [6]
。比较数组时,衰减会指向指向数组第一个元素的指针-char*
。因此,您正在比较两个指针,结果是不可预测的,因为您不知道这些字符串文字-“ hello”和“ world”如何位于内存中-地址较低。
您将获得0(这是不可能的,因为作为字符串文字的 hello 和 world 不能占据相同的内存)
if(val1 < val2) return -1;
if(val2 > val1) return 1; // condition val1 > val2 was not tested
// return 0
一样。 应该是:
if(val1 < val2) return -1;
if(val1 > val2) return 1;
访问godbolt,查看行时生成了什么代码
std::string v1= "hello", v2 = "world";
被评论。
[1]取消注释后的代码为:
.LC0:
.string "hello"
.LC1:
.string "world"
main:
push rbp
mov rbp, rsp
push rbx
[2]发表评论
.LC0:
.string "world"
.LC1:
.string "hello"
main:
push rbp
mov rbp, rsp
mov esi, OFFSET
您现在看到了吗? LC0
和LC1
是标签内存(比较了一些值),这就是为什么输出不可预测的原因,它取决于编译器如何在内存中首先存储字符串文字。
答案 1 :(得分:1)
未定义行为,例如使用<
之类的操作符指向未指向正常数组元素的指针。不同的字符串文字是不同的数组,并且衰减到指向不同数组元素的指针。任何结果都是可能的。程序可能会打印0,或者崩溃,或者发射核弹头,或者今天做这些事情之一,明天做另一件事。当然,带有UB的两个程序在看似无关的细节上有所不同(例如v1,v2),它们的行为也可能有所不同。没有一个是可以预见的。