0

这是一个简单的代码,最多返回两个输入,以练习在 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;
}
4

2 回答 2

4

模板函数的模板参数是const char *由于这个调用推导出来的

maxx("Hello","World")

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

于 2019-12-15T18:39:25.800 回答
0

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

那么为什么取消注释时顺序会改变string s = "Hello";?因为您在这样做时引入了另一个const char *值,并且编译器将为另一个使用相同的地址,因为这些 const char 不得更改,并且似乎从后到前评估参数。Hello= "Hello"Hellomaxx("Hello","World")gccmaxx("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:
        …

因为Hellois 在这种情况下首先在string s = "Hello";beforemaxx("Hello","World")被评估,所以Hello在这种情况下,第一个 const 字符串添加到数据部分 then World

如果您string s2 = "World";在您之前添加一个,string s那么订单将再次更改:

    string s2 = "World";
    string s = "Hello";
    cout<<maxx("Hello","World")<<"\n";
.LC0:
        .string "World"
.LC1:
        .string "Hello"
.LC2:
        .string "\n"
main:
    …
于 2019-12-15T19:02:45.023 回答