У меня такой код:

#include <functional>
#include <memory>
#include <string>
#include <iostream>

struct A{
    int i = 5;
};


class B{
    std::unique_ptr<A> a;
    std::function<void (void)> f;

    public:
    B(std::unique_ptr<A> a) 
        : a(std::move(a)), 
        f([&](){
                std::cout << a->i << '\n'; //segfaults when executing a->i
                })
    {}

    B()
        : a(new A),
        f([&](){
                std::cout << a->i << '\n'; //works fine 
                })
    {}

    void execLambda(){
        f();
    }

    void exec(){
       std::cout << a->i << '\n'; //works fine 
    }
};

int main(){

    B b1;
    b1.exec(); //works fine
    b1.execLambda(); //works fine

    B b2(std::unique_ptr<A>(new A));
    b2.exec(); //works fine
    b2.execLambda(); //will segfault
    return 0;

}

Кажется, когда объект заявляет о праве собственности на существующий unique_ptr и использует этот unique_ptr в лямбде, возникает ошибка сегментации. Почему в этом конкретном случае возникает ошибка сегментации? Есть ли способ использовать unique_ptr в лямбде, где было передано право собственности?

Большое спасибо!

0
DanB91 12 Сен 2013 в 00:59
6
Предположительно, я бы сказал, что лямбда захватывает a из конструктора - того, из которого вы двигаетесь, а не того, что находится внутри класса.
 – 
Jonathan Potter
12 Сен 2013 в 01:01
2
Не давать всему одно и то же имя? :-)
 – 
Kerrek SB
12 Сен 2013 в 01:03
Что сказал Джонатан, это определенное поведение
 – 
sehe
12 Сен 2013 в 01:05
@ Джонатан: Вот и все! Не могу поверить, что не осознавал этого. Большое спасибо!
 – 
DanB91
12 Сен 2013 в 01:09

1 ответ

Лучший ответ

Не называйте элементы и аргументы метода одним и тем же. Однако, если вы настаиваете на этом, вы сможете изменить лямбда-захват на [this] вместо [&], чтобы решить проблему.

Как сказал комментатор:

Предположительно, я бы сказал, что лямбда захватывает a из конструктора - того, из которого вы переходите, а не из класса. - Джонатан Поттер

1
David 12 Сен 2013 в 01:06