Построение std :: пары целых чисел с переменной с помощью постинкремента - PullRequest
6 голосов
/ 03 мая 2020

Я пытался создать пары целых чисел, где второе целое больше первого на 1:

1 2
2 3
3 4

Используя оба std::make_pair и конструктор, вот так:

std::make_pair(n, n++);

Однако это приводит к тому, что пары будут в обратном порядке:

2 1
3 2
4 3

Если бы я должен был добавить постинкремент к первому параметру или использовать вместо него (n+1), я получил бы желаемый результат.

Почему он так себя ведет?

Ответы [ 2 ]

6 голосов
/ 03 мая 2020

Это связано с порядком оценки . Начиная с cppreference.com

Порядок вычисления любой части любого выражения, включая порядок вычисления аргументов функции, не указан. Компилятор может вычислять операнды и другие подвыражения в любом порядке и может выбирать другой порядок, когда то же выражение вычисляется снова .

Поэтому Нельзя гарантировать, что n или n++ будут оцениваться первыми.

5 голосов
/ 03 мая 2020

С cppreference :

При вызове функции (независимо от того, является ли функция встроенной или нет, используется ли явный синтаксис вызова функции), вычисление каждого значения и Побочный эффект, связанный с любым выражением аргумента или с выражением постфикса, обозначающим вызываемую функцию, секвенируется перед выполнением каждого выражения или оператора в теле вызываемой функции.

Итак, что здесь происходит это.

int n = 0;
auto p = std::make_pair( n, n++ );

Сначала мы определим перегрузку make_pair; мы получаем:

make_pair<int&, int>( int&, int&& )

ie, первый аргумент является ссылкой rvalue (которая заканчивается привязкой к n), второй - ссылкой lvalue (которая заканчивается привязкой к временному that n++ возвращает).

Мы оцениваем аргументы make_pair. Они упорядочены произвольным образом, но вы увидите, что здесь это не имеет значения.

Привязка n к int& не копирует значение, а просто хранит ссылку.

Привязка n++ к int&& создает временный объект, копирует в него значение n, а затем устанавливает побочный эффект для увеличения n впоследствии.

Когда происходит побочный эффект здесь ключ Как отмечалось выше, это должно произойти до того, как будет вызвана функция make_pair.

Это может произойти до того, как n будет вычислено для первого аргумента или после; это не имеет значения, потому что мы связываем ссылку с n с аргументом. Однако оно оценивается до того, как мы сделаем тело для make_pair.

Таким образом, в пределах make_pair гарантируется ссылка на n, значение которого равно 1 и ссылка на временное значение, значение которого 0. Затем он запускает и возвращает пару с этими значениями.


Похоже, вы неправильно поняли, что означает n++ - это значит «вернуть значение n, а затем увеличить его», оно не означает «вернуть значение 1 больше n».

То, как вы возвращаете значение 1 больше n, равно n+1.

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