Комментарии 8
редкоиспользуемых нововведениях в C++11 – смарт-поинтерах
Ну не сказал бы.
Да, вроде как
std::vector<MyFileType>
может быть использовано только в С++11, т.к. у std::unique_ptr
есть только конструктор перемещения, т.е. в вектор его можно положить, если у того тоже он есть.Спасибо, за статью!
Если производительность критична, то в последнем примере я бы не стал заворачивать лямбду в function. Зачем лишние накладные расходы на упаковку и полиморфный вызов?
Здесь еще более серьезная проблема в том, что Вы выделяете через new HMODULE память под хендл в куче и не освобождаете ее, Вы ведь заместили deleter по-умолчанию своим, не так ли? Исправляем вот так:
В итоге, я бы извратился еще проще:
Никаких new, delete и куч. Для shared_ptr примера то же самое.
С Наступающим, Вас и всех!
Если производительность критична, то в последнем примере я бы не стал заворачивать лямбду в function. Зачем лишние накладные расходы на упаковку и полиморфный вызов?
auto lambda = [](HMODULE* instance){ FreeLibrary(*instance); };
auto my_instance = std::unique_ptr<HMODULE, decltype(lambda)>
(new HMODULE(LoadLibrary(_T("my_library.dll"))), lambda);
FreeLibrary(*instance) теперь просто заинлайнится.Здесь еще более серьезная проблема в том, что Вы выделяете через new HMODULE память под хендл в куче и не освобождаете ее, Вы ведь заместили deleter по-умолчанию своим, не так ли? Исправляем вот так:
auto lambda = [](HMODULE* instance){ FreeLibrary(*instance); delete instance;};
В итоге, я бы извратился еще проще:
auto lambda = [](HINSTANCE instance){ FreeLibrary(instance); };
auto my_instance = std::unique_ptr<HINSTANCE__, decltype(lambda)>
(LoadLibrary(_T("my_library.dll")), lambda);
Никаких new, delete и куч. Для shared_ptr примера то же самое.
С Наступающим, Вас и всех!
Осталось дождаться (или написать самому) std::make_unique, чтобы переложить написание всех этих decltype на ADL.
К сожалению, у Microsoft реализации STL обычно запаздывают за компилятором (по понятным причинам), но ADL то есть!
Поэтому для тех, кто не ждет:
Не хотелось загромождать этим пост, хотя не спорю, что так безопаснее.
Поэтому для тех, кто не ждет:
- Подойдет для всего, что умеет unique_ptr и forward: pastebin.com/3vU6CAnN
- Более простой вариант для VS2012: stackoverflow.com/a/13883981/1190077
Не хотелось загромождать этим пост, хотя не спорю, что так безопаснее.
make_unique уже в VS 2013.
В примере с fopen/fclose плохо то, что fclose будет вызван даже в случае, если fopen был неуспешен (возвратил null pointer). Насколько безопасно вызывать fclose для null pointer (стандарт как бы говорит нам, что behavior undefined)? Поэтому вариант с лямбдой, в которой добавлена проверка, что освобождаемый ресурс был инициализирован, кажется более подходящим.
Да и вообще, RAII-шаблон для произвольного типа у которого есть deleter(T) и T(invalid_value) пишется легко и непринуждённо (с поддержкой move семантики, ежели захочется) — примеров в интернетах море. Мне кажется он будет несколько проще, чем обёрнутый/допиленный unique_ptr.
Да и вообще, RAII-шаблон для произвольного типа у которого есть deleter(T) и T(invalid_value) пишется легко и непринуждённо (с поддержкой move семантики, ежели захочется) — примеров в интернетах море. Мне кажется он будет несколько проще, чем обёрнутый/допиленный unique_ptr.
Нет, этот вариант вполне уместен. Согласно стандарта С++11 в моём примере функция fclose будет вызвана только тогда, когда fopen вернет что-то отличное от nullptr.
20.7.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]
1. Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior,
and shall not throw exceptions.
2. Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).
and shall not throw exceptions.
2. Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Смарт-поинтеры и RAII на службе программиста