Mac和Linux中const auto&for C ++的不同行为

时间:2019-03-29 18:41:38

标签: c++ linux macos

我目前在Mac和Linux中面临不同的行为问题。我在文件test_max.cpp中有以下代码。

#include <iostream>
#include <algorithm>

float func(float a) {
    float b = a;
    return b;
}

int main() {
    float a = 0.6, b = 1;

    const auto& a1 = func(a);
    const auto& b1 = func(b);
    const auto& res1 = std::max(func(a), func(b));
    const auto& res2 = std::max(a1, b1);

    std::cout << "res1: " << res1 << std::endl;
    std::cout << "res2: " << res2 << std::endl;
}

这就是我编译代码的方式。

g++ -std=c++11  -01 -o test_max test_max.cpp && ./test_max

在Mac上,它为res1res2返回的值与1相同。但是,在Linux上,它总是为res1返回0。我不知道为什么有人可以帮我吗?

1 个答案:

答案 0 :(得分:4)

当您在不同的编译器下看到不同的行为时,您很可能处于未定义行为(或可能只是未指定行为)的领域。在这种情况下,未定义的行为来自访问悬空引用(res1)。

  

const auto& res1 = std::max(func(a), func(b));

此行将res1初始化为对std::max返回值的引用,从而设置了悬挂引用的可能性。先验地,这只是一种可能性;一些看起来相似的线不会创建悬空的引用。要查看的第一个因素是最外部的函数std::max。如果该函数按值返回(也就是返回一个临时变量),则该临时变量的生存期将延长,以使res1不会晃晃。但是,情况并非如此,因为它返回一个引用。不仅是任何引用,而且是对其参数之一的引用。不过,只要返回的参数本身不是临时的,就可以了。 {,func()返回的是值,而不是引用。因此,我们确实处境很糟。

  1. max的参数是临时参数。
  2. max返回对其参数的引用。

这是Lifetime of a temporary @ cppreference.com的第三个项目符号中描述的情况。结果是一个悬空的引用,访问它以打印其值会调用未定义的行为。


可能有趣的是,添加另一个函数调用可以解决未定义的行为:

const auto& res1 = func(std::max(func(a), func(b)));

当然,如果func不是身份功能,那将改变功能。但是,就未定义行为而言,最外面的func返回的值是func(b)返回的临时值的副本。它是一个立即绑定到参考变量的新临时变量,因此其寿命得以延长。一切都很好。

然后,针对该行的更典型的解决方法是删除与号...
嗯,学习运动。