Передача этой лямбды в `unique_ptr` в порядке? - PullRequest
2 голосов
/ 02 ноября 2019

Я придумываю такой код.

Передает ли эту лямбду методу unique_ptr в методе ptr ОК на всю жизнь?

#include <memory>

#include <cstdlib>

#include <cstdio>

struct MallocAllocator{
    static void *allocate(size_t size) noexcept{
        return malloc(size);
    }

    /* static */ void deallocate(void *p) noexcept{
        printf("%d\n", x); // debug
        return free(p);
    }

    template<class T>
    auto ptr(T *p){
        auto x = [me = this](T *p){
            me->deallocate(p);
        };

        return std::unique_ptr<T, decltype(x)>{ p, x };
    }

    int x; // debug

    MallocAllocator(int x) : x(x){}
};

MallocAllocator allocator{5};

int *getInt(MallocAllocator &allocator){
    return (int *) allocator.allocate(sizeof(int));
}

int main(){
    auto a = allocator.ptr( getInt(allocator) );
}

1 Ответ

3 голосов
/ 02 ноября 2019

Лямбда - это объект, и вы можете хранить его так, как считаете нужным. Вы должны убедиться в том, что время жизни любых ссылок или указателей на них хранится.

Если вы перехватываете копию (=), вы всегда в безопасности. В вашем примере вы захватываете указатель this, что также хорошо, если объект переживет ваш unique_ptr (в данном случае это глобальный объект).

Обратите внимание, что ввод локальных указателей является ошибкойили ссылки указателем / ссылкой, потому что они выпадают из области видимости и становятся недействительными, даже если объект, на который они указывают, переживает:

auto ref = this;
auto lambda = [&] () { this->… }; // ok if parent object outlives lambda
auto lambda = [&] () { ref->… }; // wrong! leads to invalid pointer

...