В то время как рефакторинг некоторых кодеков сегодня, чтобы изменить исходные указатели на std::unique_ptr
, я столкнулся с проблемой сегментации из-за ошибки order of evaluation.C++ 17 выражение оценки порядка и std :: move
старый код сделал что-то вроде следующего:
void add(const std::string& name, Foo* f)
{
_foo_map[name] = f;
}
void process(Foo* f)
{
add(f->name, f);
}
Первый, наивные, рефакторинга кода использовать std::unique_ptr
:
void add(const std::string& name, std::unique_ptr<Foo> f)
{
_foo_map[name] = std::move(f);
}
void process(std::unique_ptr<Foo> f)
{
add(f->name, std::move(f)); // segmentation-fault on f->name
}
после рефакторинга кода вызывает ошибку сегментации, поскольку Второй аргумент (std::move(f)
) обрабатывается первым, а затем 1-й аргумент (f->name
) разыменовывает перемещенную переменную, стрелу!
Возможные исправления для этого должны получить ручку на Foo::name
перед тем перемещая его в вызове add
:
void process(std::unique_ptr<Foo> f)
{
const std::string& name = f->name;
add(name, std::move(f));
}
Или, может быть:
void process(std::unique_ptr<Foo> f)
{
Foo* fp = f.get();
add(fp->name, std::move(f));
}
Оба эти решения требуют дополнительных линий кода и не кажутся почти такими же сложными, как и исходный (хотя и UB) вызов add
.
Вопросы:
ли либо из 2 предложенных решений выше идиоматической C++, а если нет, то есть лучшая альтернатива?
Я вижу, что есть перемены приходящих n C++ 17 из-за P0145R3 - Refining Expression Evaluation Order for Idiomatic C++. Изменит ли это какое-либо из вышеупомянутых решений/предотвратит их подводные камни?
Я бы сказал, что «идиоматическим» решением было бы реорганизовать функцию «добавить» или добавить перегрузку, которая принимает объект 'std :: unique_ptr'. –
@Someprogrammerdude, который просто переместил бы требование получить дескриптор по имени из 'process', чтобы' add' хотя правильно? Или P0145R3 решает эту проблему? –
IMO - это, как правило, хорошая идея подталкивать эти детали как можно дальше по стеку. Абстракция - одна из основных частей OO и C++. –