Я наткнулся на код, похожий на этот, при отладке сбоя из-за удаления ссылки на оборванную часть памяти.Копирование x-значения по значению, возвращаемому функцией
template<typename RaiiObject, typename HandleType>
const HandleType& ExtractHandle(const RaiiObject &value){
const HandleType* val = value.get(); // get underlying managed object
return static_cast<const HandleType&>(*val);
}
На стороне вызывающего абонента, код выглядит следующим образом:
const auto &x = ExtractHandle(GetAHandle());
Это определенно проблема, потому что ссылка на основной объект, который мы будем получать от ExtractHandle
будет болтая с Raii управление объектом было бы истекло.
Теперь разработчик, устраняющий эту проблему, заменил захват по ссылке на захват по значению.
auto x = ExtractHandle(GetAHandle());
Его утверждение, что, так как мы делаем копию, мы безопасны , так как х-значение, возвращаемое GetAHandle не умрёт, пока конструктор копирования для Handle вызывается. Правильно ли это предположение? Хорошо ли определено стандартом, что выше предлагаемое исправление не является UB?
Примечание: В то время как правильность и полезность этого дизайна, безусловно, может быть поставлена под сомнение, точка больше вокруг копирование по значению, гарантирует ли хорошо определенное поведение
он правильный, но код все еще мусор. make ExtractHandle вернет копию и сделайте с ней. Кроме того, зачем отбрасывать const? зло! –
Несвязанный, но вы не можете сказать 'return * val;' вместо 'return static_cast (* val);'? –
juanchopanza
Большая проблема заключается в том, что 'RaiiObject :: get()' может возвращать копию. Поэтому 'val' будет указателем на rvalue. Я не знаю, как долго сохраняются значения, но я бы предположил, что копия даже не сохранится до заявления о возврате. В самом начале он будет уничтожен, когда функция завершится. Итак, если 'RaiiObject :: get()' возвращает копию 'ExtractHandle()' гарантированно возвращает недопустимую ссылку. – kamikaze