首页 > 解决方案 > 为什么即使函数调用中没有任何更改,函数也会返回两个不同的值?

问题描述

在第一种情况下,代码返回 -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。

标签: c++11

解决方案


在这两种情况下T都推断为char [6]。在比较数组衰减到指向数组第一个元素的指针时 - char*。所以你正在比较两个指针,结果是不可预测的,因为你不知道这些字符串文字 - “hello”和“world”是如何定位到内存中的 - 它具有较低的地址。

你得到 0 (这应该是不可能的,因为helloworld作为字符串文字不能占用相同的内存)因为这些条件

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是标签内存(一些比较的值),这就是为什么输出是不可预测的,这取决于编译器如何在内存中存储字符串文字,这是第一个。


推荐阅读