Различное поведение в const auto и для C ++ в Mac и Linux - PullRequest
0 голосов
/ 29 марта 2019

В настоящее время у меня проблемы с поведением в 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 он возвращает мне одинаковое значение для обоих res1 и res2 как 1. Однако в linux он всегда возвращает 0 для res1.Я не знаю почему.Может ли кто-нибудь мне помочь?

1 Ответ

4 голосов
/ 30 марта 2019

Когда вы видите различное поведение в разных компиляторах, вы, скорее всего, находитесь в области неопределенного поведения (или, возможно, просто неопределенного поведения). В этом случае неопределенное поведение происходит из-за доступа к висячей ссылке (res1).

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

Эта строка инициализирует res1 как ссылку на то, что возвращает std::max, устанавливая возможность висячей ссылки. Априори, это просто возможность; некоторые похожие линии не создают висячих ссылок. Первый фактор, на который стоит обратить внимание, - это самая внешняя функция, std::max. Если бы эта функция возвращала по значению (a.k.a. вернула временное), время жизни этого временного объекта было бы продлено, чтобы res1 не зависало. Однако это не так, поскольку он возвращает ссылку. Не просто ссылка, а ссылка на один из ее параметров. Тем не менее, это нормально, если возвращаемый параметр не является временным. Увы, func() возвращает по значению, а не по ссылке. Так что мы действительно в плохом деле.

  1. Параметр max является временным.
  2. max возвращает ссылку на свой параметр.

Это ситуация, описанная в третьем пункте Время жизни временного @ cppreference.com. Результатом является свисающая ссылка, и доступ к ней для печати ее значения вызывает неопределенное поведение.


Может быть интересно отметить, что добавление еще одного вызова функции может разрешить неопределенное поведение:

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

Конечно, если бы func было чем-то отличным от функции идентификации, это изменило бы функциональность. Но, что касается неопределенного поведения, значение, возвращаемое внешним func, является копией временного значения, возвращаемого func(b). Это новое временное существо, немедленно связанное со ссылочной переменной, поэтому его время жизни увеличивается. Все хорошо.

Опять же, более типичным исправлением для этой линии будет удаление амперсанда ...
Эх, учебное упражнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...