Захвачен ли захват, даже если он не используется? - PullRequest
0 голосов
/ 18 мая 2018

Я использую асинхронную функцию, которая принимает ссылку на объект &foo и обратный вызов cb в качестве аргументов.Я хочу предотвратить уничтожение foo до тех пор, пока не будет вызван обратный вызов.

void async_thing(Foo &foo, function<void()> cb) {
    // do something asynchronously with foo
}

Достаточно ли просто перехватить его в лямбде обратного вызова?Или это действительно нужно использовать в лямбде?

auto foo = make_shared<Foo>();
async_thing(*foo, [foo]() {
    cout << "Callback ran" << endl;
});

Может ли компилятор оптимизировать захват и преждевременно удалить foo?

1 Ответ

0 голосов
/ 19 мая 2018

n3690, раздел 5.1.2

15. Сущность захватывается копией, если она неявно захвачена, а значение захвата по умолчанию равно =или если он явно захвачен с захватом, который не включает &.Для каждого объекта, захваченного копией, неназванный элемент нестатических данных объявляется в типе замыкания.

Выше которого имеем:

3. Тип лямбда-выражения (который также является типом объекта замыкания) является уникальным, безымянным типом класса несоединения, называемым типом замыкания.
[…]
Реализация может определять тип замыкания иначе, чемчто описано ниже, при условии, что это не изменяет наблюдаемое поведение программы, кроме как путем изменения:

  • размера и / или выравнивания типа замыкания,
  • независимо от типа замыканиякопируется тривиально (пункт 9),
  • независимо от того, является ли тип замыкания классом стандартной компоновки (пункт 9), или
  • , является ли тип замыкания классом POD (пункт 9).

Из этого я бы заключил, что:

  • Захват делает элемент shared_ptr в типе закрытия.
  • Компилятору не разрешеноизменить эту обсерву
  • Таким образом, ваш указатель не будет удален, пока не будет вызван деструктор замыкания.
...