为什么在C++中使用关系运算符创建的模板函数不能对字符串正常工作?



这是一个简单的代码,最多返回两个输入,以练习在C++中使用模板函数。代码将输出打印为"Hello",这是错误的,当我们取消注释行{string s = "Hello";}时,输出变得正确,即使使用的"Hello"不是s。 代码运行的屏幕截图

#include <iostream>
using namespace std;
template <typename T>
T maxx(T a, T b)
{
if (a>b) {return a;}
return b;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// string s = "Hello";
cout<<maxx("Hello","World")<<"n";
return 0;
}

由于此调用,模板函数的模板参数被推导为const char *

maxx("Hello","World")

因此,将比较指向字符串文本的第一个字符的指针。比较的结果取决于编译器在文本池中放置文本的顺序。

正如在另一个答案中已经说过的,maxx函数作为参数const char *,因此您比较指针,结果取决于编译器在数据部分中放置HelloWorld的顺序。

那么,为什么当您取消注释string s = "Hello";时顺序会发生变化?因为您在执行= "Hello"时引入了另一个具有值Helloconst char *,并且编译器将对maxx("Hello","World")的其他Hello使用相同的地址,因为这些常量字符不得更改,并且gcc似乎从后到前评估maxx("Hello", "World")的参数。

所以对于gcc

int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// string s = "Hello";
cout<<maxx("Hello","World")<<"n";
return 0;
}

将导致:

.LC0:
.string "World"
.LC1:
.string "Hello"
.LC2:
.string "n"
main:
push    rbp
mov     rbp, rsp
mov     edi, 0
call    std::ios_base::sync_with_stdio(bool)
mov     esi, 0
mov     edi, OFFSET FLAT:_ZSt3cin+16
call    std::basic_ios<char, std::char_traits<char> >::tie(std::basic_ostream<char, std::char_traits<char> >*)
mov     esi, OFFSET FLAT:.LC0
mov     edi, OFFSET FLAT:.LC1
call    char const* maxx<char const*>(char const*, char const*)
mov     rsi, rax
mov     edi, OFFSET FLAT:_ZSt4cout
call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
mov     esi, OFFSET FLAT:.LC2
mov     rdi, rax
call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
mov     eax, 0
pop     rbp
ret

如果您现在取消注释string s = "Hello";,将导致:

.LC0:
.string "Hello"
.LC1:
.string "World"
.LC2:
.string "n"
main:
…

由于在这种情况下,Hello首先在string s = "Hello";中找到,然后再计算maxx("Hello","World"),因此在这种情况下,Hello是添加到数据部分的第一个常量字符串,然后World

如果您在string s之前添加string s2 = "World";,则顺序将再次更改:

string s2 = "World";
string s = "Hello";
cout<<maxx("Hello","World")<<"n";
.LC0:
.string "World"
.LC1:
.string "Hello"
.LC2:
.string "n"
main:
…

最新更新