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

标签 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。我不知道为什么。有人可以帮助我吗?

最佳答案

当您在不同的编译器下看到不同的行为时,您很可能处于未定义行为的领域(或者可能只是未指定的行为)。在这种情况下,未定义的行为来自于访问悬空引用 (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) 返回的临时值的拷贝。它是一个新的临时变量,立即绑定(bind)到引用变量,因此它的生命周期得到延长。一切都很好。

话又说回来,此行更典型的修复方法是删除&符号...
嗯,学习练习。

关于c++ - Mac 和 Linux 中 C++ 的 const auto& 的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55423740/

相关文章:

c++ - C++ 中的动态数组(用指针表示)- 输入元素?

c++ - 在 C++ 中处理浮点异常

linux - 队列的实现给出运行时错误

php - 如何在 Linux 上使用 PHP 从本地主机发送电子邮件

C++ 在调试版本中抑制断言

c++ - mmap小尺寸内存,当munmap时,glibc会释放映射内存给操作系统吗?

linux - Groovy:找不到适合的 ClassLoader 以供抓取

c++ - OpenGL - 为什么我会收到此错误?不支持 COMPILATION_FAILED 版本 '330'

macos - 如何在 OSX 终端中获得滚动转换?

java - 用于 C/C++ 和 Java 的 Eclipse IDE