У меня есть функция, которая работает с большим куском данных, переданным в качестве аргумента приемника. Мой тип BigData
уже поддерживает C++11 и поставляется с полнофункциональным конструктором перемещения и реализациями присваивания перемещения, так что я могу уйти без необходимости копировать эту чертову штуку:
Result processBigData(BigData);
[...]
BigData b = retrieveData();
Result r = processBigData(std::move(b));
Все это прекрасно работает. Однако моя функция обработки может время от времени давать сбой во время выполнения, что приводит к исключению. На самом деле это не проблема, так как я могу просто исправить вещи и повторить попытку:
BigData b = retrieveData();
Result r;
try {
r = processBigData(std::move(b));
} catch(std::runtime_error&) {
r = fixEnvironmnentAndTryAgain(b);
// wait, something isn't right here...
}
Конечно, это не сработает.
Поскольку я переместил свои данные в функцию обработки, к тому времени, когда я попаду в обработчик исключений, b
уже нельзя будет использовать.
Это угрожает резко снизить мой энтузиазм по поводу передачи аргументов стока по значению.
Итак, вот вопрос: как справиться с такой ситуацией в современном коде C++? Как получить доступ к данным, которые ранее были перемещены в функцию, которую не удалось выполнить?
Вы можете изменить реализацию и интерфейсы для BigData
и processBigData
по своему усмотрению. Однако окончательное решение должно попытаться свести к минимуму недостатки исходного кода в отношении эффективности и удобства использования.
Result
просто вычисляется изb
, оно не содержит ссылку или копию исходногоb
. - person ComicSansMS   schedule 04.09.2014b
отбрасывается функцией обработки, как только она возвращается. - person ComicSansMS   schedule 04.09.2014const&
мне потребовалось бы скопировать все данные (на самом деле я столкнулся с этой проблемой в функции асинхронной обработки, поэтому право собственности на данные действительно нужно передать функции). Лучшее решение, которое я мог бы придумать, чтобы избежать копирования, - это использовать shared_ptr и пройти через кучу, но я бы хотел избежать этого, если это возможно. - person ComicSansMS   schedule 04.09.2014Result processBigData(BigData&& in_ref, BigData* out_ref=NULL){BigData whereitmoves(std::foreward(in_ref));try{/*old method*/}catch(...){if (out_ref){*out_ref=std::move(whereitmoves);} std::rethrow_exception(std::current_exception());}
- person IdeaHat   schedule 04.09.2014