这是一个简单的代码,最多返回两个输入,以练习在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 *
,因此您比较指针,结果取决于编译器在数据部分中放置Hello
和World
的顺序。
那么,为什么当您取消注释string s = "Hello";
时顺序会发生变化?因为您在执行= "Hello"
时引入了另一个具有值Hello
const 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:
…