const auto & to integer с помощью std :: min std :: max - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть эти коды ниже. Что не так с const auto& в этом контексте, это вызвало неожиданные результаты.

Отлично работает при компиляции с g cc -4.8.5, но получает неожиданные результаты с g cc -4.9.2.

Если я удаляю & in const auto&, он отлично работает с обеими версиями g cc.

// max_dim is a protobuf filed: const auto max_dim = msg.max();
// cat2_num is an element in std::vector<int32_t>: const auto cat2_num = vec[i]
const auto& res_num = std::max(1, std::min(max_dim, cat2_num));
LOG(ERROR) << res_num << ", " << max_dim << ", " << cat2_num
   << ", " << std::max(1, std::min(max_dim, cat2_num));

вывод:

 -1392522416, 3, 1, 1
 2, 3, 2, 2
 3, 3, 3, 3
 -1392522416, 3, 1, 1
 3, 3, 6, 3
 2, 3, 2, 2
 -1392522416, 3, 1, 1
 -1392522416, 3, 1, 1
 2, 3, 2, 2

=========== updated ==== ====

Я не смог воспроизвести неопределенное поведение с этими кодами:

#include <iostream>
#include <vector>

int main() {
    std::vector<int32_t> v = {-1, 0, 1, 2, 3, 6};
    const int a = 3;
    const auto& b = a;

    for(size_t i = 0; i < v.size(); i++) {
        const auto& c = v[i];
        const auto& d = std::max(1, std::min(b, c));
        std::cout << d << ", " << b << ", " << c << std::endl;
    }
    return 0;
}

вывод:

1, 3, -1
1, 3, 0
1, 3, 1
2, 3, 2
3, 3, 3
3, 3, 6

Ответы [ 2 ]

8 голосов
/ 13 апреля 2020

Ваш код имеет неопределенное поведение. В

const auto& res_num = std::max(1, std::min(max_dim, cat2_num));

1 является prvalue, поэтому создается временное целое число, которое связывается с параметром функции. Это было бы нормально, если бы max был похож на

template <typename T> const T max(const T&, const T&);

, но вместо этого он определен как

template <typename T> const T& max(const T&, const T&);

Итак, если это 1 окажется максимальным значением, то max возвращает вам ссылку на тот временный объект, который был создан. После этого временный объект уничтожается 1 , оставляя res_num в качестве свисающей ссылки. Чтобы исправить код, сделайте res_num не ссылочным, как

const auto res_num = std::max(1, std::min(max_dim, cat2_num));

, и теперь вы получите копию правильного значения.

1: все временные объекты уничтожаются при конец полного выражения создан в

0 голосов
/ 14 апреля 2020

@ НатанОливер дал четкое объяснение причины. Вот некоторая другая связанная информация.

  1. const T& полезна для крупных объектов, но она связана с проблемами lifetime и aliasing. Так что будьте осторожны.

  2. Для значений int, double, pointers, const T& ничего не дает. В этой ситуации copy дешевле, чем reference.

ссылка: int против const int &

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