Pull to refresh

Comments 8

редкоиспользуемых нововведениях в C++11 – смарт-поинтерах

Ну не сказал бы.

Да, вроде как std::vector<MyFileType> может быть использовано только в С++11, т.к. у std::unique_ptr есть только конструктор перемещения, т.е. в вектор его можно положить, если у того тоже он есть.
С указанием функции освобождения ресурса используется не так часто, как без. Да, unique_ptr является частью стандартной библиотеки шаблонов C++11, где и все контейнеры умеют работать с типами, которые можно только перемещать (но не копировать).
Спасибо, за статью!

Если производительность критична, то в последнем примере я бы не стал заворачивать лямбду в 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 то есть!
Поэтому для тех, кто не ждет:
  1. Подойдет для всего, что умеет unique_ptr и forward: pastebin.com/3vU6CAnN
  2. Более простой вариант для VS2012: stackoverflow.com/a/13883981/1190077

Не хотелось загромождать этим пост, хотя не спорю, что так безопаснее.
В примере с fopen/fclose плохо то, что fclose будет вызван даже в случае, если fopen был неуспешен (возвратил null pointer). Насколько безопасно вызывать fclose для null pointer (стандарт как бы говорит нам, что behavior undefined)? Поэтому вариант с лямбдой, в которой добавлена проверка, что освобождаемый ресурс был инициализирован, кажется более подходящим.

Да и вообще, 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()).
Sign up to leave a comment.

Articles

Change theme settings