Почему unique_ptr с пользовательским удалением не будет работать для nullptr, а shared_ptr работает? - PullRequest
0 голосов
/ 06 мая 2018

Простой код для использования unique_ptr или shared_ptr в качестве охраны области. Вся информация о том, что нужно очистить, содержится в deleter, поэтому я уверен, что для конструктора безопасно использовать nullptr.

Очевидно, что в Visual C ++ 2017 (14.1) он не работает должным образом для unique_ptr, но работает для shared_ptr. Это выдумка Microsoft или стандарт запрещает вызывать deleter из unique_ptr при удержании nullptr?

В приведенном ниже коде я вынужден создать unique_ptr с (void*)1. Если я построю это с nullptr, cleaner не будет вызван. Для shared_ptr разницы нет, всегда вызывается cleaner.

#include <memory>
#include <iostream>

int main()
{
    int ttt = 77;

    auto cleaner = [&ttt](void*) {
        std::cout << "cleaner: " << ttt << "\n"; // do something with capture here instead of print
    };

    std::unique_ptr<void, decltype(cleaner)> p((void*)1, cleaner);

    std::shared_ptr<void> q(nullptr, [&ttt](void*) {
        std::cout << "shared: " << ttt << "\n"; // do something with capture here instead of print
    });

    std::cout << "done\n";
    return 0;
}

1 Ответ

0 голосов
/ 06 мая 2018
Для этого требуется деструктор

unique_ptr:

23.11.1.2.2 деструктор unique_ptr [unique.ptr.single.dtor]

2 Эффекты: если get() == nullptr, то никаких эффектов нет. В противном случае get_deleter()(get()).

на самом деле деструктор shared_ptr должен сделать то же самое:

23.11.2.2.2 деструктор shared_ptr [util.smartptr.shared.dest]

- (1.1) Если *this пусто или владеет другим владельцем shared_ptr (use_count() > 1), побочные эффекты отсутствуют.

- (1.2) В противном случае, если *this владеет объектом p и вызывается средство удаления d, вызывается d (p).

Таким образом, использование интеллектуальных указателей для выполнения произвольных действий при выходе из области действия при передаче нулевых указателей ненадежно.

...