Интегральное продвижение при передаче и возврате аргумента по ссылке?
Я читаю кое-что о разрешении перегрузки, и я нашел то, что беспокоит меня... В следующем коде:
int const& MaxValue(int const& a, int const& b)
{
return a > b ? a : b;
}
void SomeFunction()
{
short aShort1 = 3;
short aShort2 = 1;
int const & r2 = MaxValue(aShort1, aShort2); // integral promotion
//is it safe to pass r2 around before function SomeFunction completes
// CallSomeOtherFunctionThatCallsSomethingElse(r2);
}
Насколько я понимаю, два временных int создаются и размещаются в стеке, принадлежащем SomeFunction. Поэтому, когда MaxValue возвращается, r2 ссылается на одну из этих временных переменных (в данном случае, ту, которая содержит значение 3). Таким образом, это должно быть безопасно, чтобы передать r2.
Вопрос в том, если мое понимание хорошо, это стандартное поведение (пожалуйста, проверьте)? Если нет, пожалуйста, объясните, что происходит в приведенном выше коде.
Большое спасибо
4 ответа
Краткий ответ: это небезопасно.
Стандарт гарантирует, что временная переменная может быть связана с постоянной ссылкой, и в этом случае срок службы временной увеличивается до времени жизни связанной ссылки. Проблема в вашем конкретном случае в том, что ссылка на самом деле обязательна для временного.
Когда вы звоните MaxValue( s1, s2 )
создаются две временные переменные типа int и привязываются к аргументам параметра a
а также b
в MaxValue
, Это означает, что срок службы этих временных сотрудников продлен до завершения функции. Теперь в операторе возврата вашей функции вы берете вторую ссылку на один из временных значений, и эта вторая ссылка не продлит срок жизни. r2
не будет продлевать срок службы объекта, и у вас есть свисающая ссылка.
Обратите внимание, что из-за отдельной компиляции компилятор не может знать извне MaxValue
является ли возвращенная ссылка одним из аргументов или совершенно другим объектом, который не является временным:
int const & OtherMaxValue( int const & a, int const & b ) {
static int value = 0;
value = (a > b? a : b);
return value;
}
Таким образом, он не может предположить, нужно ли продлевать какое-либо время жизни.
В качестве примечания, для небольших объектов (таких как все целочисленные типы) передача по ссылке может быть на самом деле хуже, чем передача по значению. Также уже есть std::max
шаблон, который фактически реализует эту функциональность.
Добро пожаловать на то, почему неявное приведение сосет. Теперь у вас есть ссылка на временный, который был уничтожен. Надеюсь, ты не хотел ничего с этим делать.
Да, ваше понимание в порядке, и это стандартное поведение.
Кроме этого:
Таким образом, это должно быть безопасно, чтобы передать r2.
чего я не понимаю.
// РЕДАКТИРОВАТЬ
Вы должны использовать указатели вместо ссылок здесь, чтобы добиться того же, но без проблем. Использовать адрес аргумента, передаваемого по константной ссылке, можно только внутри функции, поскольку он может указывать на локальную копию объекта.