3

当我看到以下工作时,我有点困惑

struct A {
    void g(){}
    void f(){
        [&](){ g(); }();
    }
};

但后来我找到this了答案,它非常详细地解释了它是如何工作的。

从本质上讲,它归结为this无论您使用[=]还是[&].

但是,在cppreference上,我阅读了以下内容

(*this)如果存在任一捕获默认值,则可以隐式捕获当前对象。如果隐式捕获,则始终通过引用捕获,即使捕获默认值为=.

所以我有两个似乎是等价的公式

  1. this[=]无论我们使用还是,都被价值捕获[&]
  2. (*this)[=]无论我们使用还是,都是通过引用捕获的[&]

首先,上面的两个公式确实是完全等价的吗?

我确实看到了两者之间的区别,如果不是在实际可能的情况下,至少在它们看起来有多有用方面。

配方 1 对我来说似乎很奇怪。为什么阻止我this通过const-reference 捕获?在性能方面,这两种情况应该没有什么大的区别,我总是可以auto const& This = this;在 lambda 之前做,然后This如果我愿意的话,可以通过引用捕获。至于悬空引用,如果我使用this关键字,我在对象类中,那么当我在其中时,对象怎么会死呢?

另一方面,公式 2 似乎确实可以保护我免于制作不必要的副本,如果(*this)在使用[=]. 此外,如果我真的想要,还有一种用于(*this)通过副本捕获的捕获语法,即[*this].

4

2 回答 2

3

第一种解释是 C++17 之前的意图(编写该答案时),但第二种解释是此后的意图(如始终存在的 cppreference 所反映的)。最初认为this指针)是捕获的主题,当然不可能通过引用来做到这一点(如所指出的;const auto &x=…;如果它引入了一个临时的,则根本不是一回事)。C++17 引入了捕获*this(按值),将现有捕获重新解释[this]为有效[&*this](这实际上不是有效的语法)。

C++20 继续过渡,弃用

struct A {
  auto f() {return [=] {return this;}}
};

因为它实际上并没有按价值捕获任何东西,相反 [=,this]它现在被认为是“按价值捕获所有东西,除了*this而不是多余的“按价值捕获所有东西,也this按价值捕获”。相反,[&,this]现在应该被认为是多余的,但它还没有被弃用(还)。

于 2021-03-08T18:09:56.210 回答
2

首先,上面的两个公式确实是完全等价的吗?

你可以认为它们在功能上是相同的,但第二个并不是最好的思考方式。this总是被价值所俘获。但是 sinethis是一个指针,被捕获的值只是指向该对象的指针。因此,您可以从概念上将其视为通过指针捕获通过引用指向的对象。

为什么阻止我通过引用来捕获它?

因为表达式this是纯右值。没有this可以引用的对象被调用。这就是为什么如果你这样做auto& This = this;,你会得到一个编译错误

记住:this是一个指向对象的指针。指针是prvalue;指向的对象不是

至于悬空引用,如果我使用 this 关键字,我在对象类中,那么当我在其中时,对象怎么会死掉呢?

除了可以调用this->~Typename()来销毁对象这一事实之外,lambda 只是一个可调用对象。它可以持续存在于创建它的位置的边界之外。它可以返回(通过类型擦除,如通过 astd::function或通过auto返回类型推导),也可以传递给其他人并存储在对象范围之外。

于 2021-03-08T17:50:15.510 回答