【问题标题】:Simple custom deleter lambda supplied to std::unique_ptr: why use by-reference capture default ([&]) over no-capture ([])?提供给 std::unique_ptr 的简单自定义删除器 lambda:为什么使用按引用捕获默认值 ([&]) 而不是无捕获 ([])?
【发布时间】:2017-02-14 12:25:59
【问题描述】:

背景

Cppreference:s section on std::unique_ptr 展示了以下演示,用于为 unique_ptr 实例提供自定义删除器:

std::unique_ptr<D, std::function<void(D*)>> p(new D, [&](D* ptr)
{
    std::cout << "destroying from a custom deleter...\n";
    delete ptr;
});

就这个问题而言,D 与简单的自定义类型一样,比如

struct D
{
    D() { std::cout << "D CTOR\n"; }
    ~D() { std::cout << "D DTOR\n"; }
};

此外,上面的参考说明了对删除器的以下类型要求:

类型要求

Deleter 必须是 FunctionObject 或左值引用 FunctionObject 或对函数的左值引用,可使用 unique_ptr&lt;T, Deleter&gt;::pointer 类型的参数

...

会员类型

pointer: std::remove_reference&lt;Deleter&gt;::type::pointer 如果该类型存在,否则T*。必须满足NullablePointer

作为上例中删除器 lambda 的捕获列表,使用了[&amp;]。根据 Cppreference:s section on lambdas,在我看来,上面删除器示例中这个捕获列表的唯一效果是捕获“当前对象通过引用” [强调我的]:

[&amp;] 捕获所有自动变量 odr-用于 lambda 引用和 如果存在则引用当前对象

但正如我从上面所理解的那样,无论我们选择[&amp;] 还是[] 作为 lambda 的捕获列表,都将简单地使用对象的 unique_ptr&lt;T, Deleter&gt;::pointer 调用提供的 lambda。我自己不明白为什么我们要使用引用捕获(object,这里是 unique_ptr 实例?)默认在这里,但我很确定我'我错过了一些必不可少的东西(因此提出了问题)。

问题

  • 与仅使用无捕获 ([]) 相比,在上述示例中的删除器 lambda 中使用按引用捕获默认值 ([&amp;]) 有什么特别的原因吗?

【问题讨论】:

  • 不太接近答案,但“当前对象”将是p 是成员函数的实例,即*this。如果p 不是成员函数,则无关紧要(因此“如果存在”)。
  • 我认为这只是一个错字,或者示例的作者并没有太在意。毕竟,这并没有降低示例的有效性,不是吗?
  • @SingerOfTheFall 感谢您的反馈。我对示例的有效性不太感兴趣,而是如果我在选择捕获列表时遗漏了一些基本意图(因为我对 C++ 的这些部分不是很精通)。如果答案是,“可能没有特别的意图;两种选择都有效”,那么我对这样的答案很满意。
  • @Quentin 我明白了,这与 SingerOfTheFall 上面的评论一致,因为在这种特殊情况下 [&amp;] 似乎是多余的(我错误地认为“当前对象”将是 @ 987654348@ 本身,因为它是调用删除器时参数的提供者)。

标签: c++ lambda


【解决方案1】:

以下是标准对 unique_ptr 删除器 ([unique.ptr.single]/1) 的说明:

客户端提供的模板参数 D 应为函数对象类型 (20.9)、函数的左值引用或函数对象类型的左值引用 为此,给定一个值 d 类型 D 和一个值 指针 类型 unique_ptr::pointer , 表达方式 d(点) 是有效的,并且具有为该删除器处理适当的指针的效果。

从以上判断,[][&amp;] 都是完全有效的。

【讨论】:

  • 感谢您的回答。在我的问题示例中,删除器是函数对象类型,对吗?我不太了解上面的标准引用如何直接应用于 lambda 中不同捕获的分析([&amp;] vs [];等价,在这里?);是在此处使用完全等效的这些替代方案,还是将使用其中一个而不是另一个意味着模板参数D 的不同类型? (在我看来,这两种情况都是函数对象类型,但我可能错了)。如果您能在此示例中扩展这两者如何等效(或不等效)的推理,我将不胜感激。
  • 每个 lambda 都有自己独特的类型,所以它总是“模板参数 D 的不同类型”。但是,对删除器的唯一要求是它应该在以d(ptr) 的形式调用时正确删除指针。其他任何关于它如何工作的东西(包括它的内部结构)都是无关紧要的。因此我得出结论,在这种情况下 [] 和 [&] lambda 是等效的(因为捕获或不捕获额外数据不会改变删除器的行为)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
相关资源
最近更新 更多