Интегральное продвижение при передаче и возврате аргумента по ссылке? - PullRequest
2 голосов
/ 04 июля 2010

Я читаю кое-что о разрешении перегрузки, и я нашел кое-что, что беспокоит меня ... В следующем коде:

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);

}

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

Вопрос в том, если мое понимание в порядке, это стандартное поведение (пожалуйста, проверьте)?Если нет, пожалуйста, объясните, что происходит в приведенном выше коде.

Большое спасибо

Ответы [ 4 ]

4 голосов
/ 04 июля 2010

Добро пожаловать, почему неявное приведение отстой. Теперь у вас есть ссылка на временный, который был уничтожен. Надеюсь, ты не хотел ничего с этим делать.

3 голосов
/ 04 июля 2010

Да, ваше понимание в порядке, и это стандартное поведение.

Кроме этого:

Таким образом, должно быть безопасно передавать r2.

которого я не понимаю.

// РЕДАКТИРОВАТЬ

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

2 голосов
/ 04 июля 2010

Краткий ответ: это небезопасно.

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

Когда вы вызываете 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, который фактически реализует эту функцию.

1 голос
/ 04 июля 2010

Вы должны вернуть и передать по значению для простых типов.

...