简体   繁体   English

为什么这个 lambda 不会通过引用通过删除的构造函数来捕获这个变量?

[英]Why won't this lambda capture this variable with a deleted constructor by reference?

My compiler, Visual Studio 19, says "Attempting to reference a deleted function":我的编译器 Visual Studio 19 显示“正在尝试引用已删除的函数”:

class AClass 
{public:
    AClass(const AClass& other) = delete;
    AClass() {}
    AClass(AClass&& other) { }
    AClass& operator=(const AClass& other) = delete;
    AClass& operator=(AClass&& other) { return *this; }
    int member;
};


void main()
{
    AClass a;
    AClass& aRef = a;

    [=]() { return aRef.member; }; // "Attempting to reference a deleted function"

}

I assume it's trying to call the copy constructor, which is deleted, but I don't understand why as I'm trying to capture by reference by [=] value, meaning I don't copy the object AClass, I don't see how any copy is involved.我假设它正在尝试调用已删除的复制构造函数,但我不明白为什么,因为我试图通过 [=] 值通过引用捕获,这意味着我不复制对象 AClass,我不看看如何涉及任何副本。 My understanding is that the lambda looks something like this:我的理解是 lambda 看起来像这样:

struct lambda {
    AClass& refToAClass; // <--- this is the captured object
    lambda(AClass& captureVariable) : refToAClass(captureVariable) {}
    int operator()() const
    {
        return refToAClass.member;
    }
};


void main()
{
      // AND I CAN CONSTRUCT THE LAMBDA, NO COPYING OF AClass INVOLVED
      AClass a;
      AClass& aRef = a;

      lambda lam(aRef); // WORKS FINE
}

How is a copy involved in this case?本案如何涉及副本? And how do I capture that reference?我如何捕获该参考?

From the standard :标准

For each entity captured by copy , an unnamed non-static data member is declared in the closure type.对于 copy 捕获的每个实体,在闭包类型中声明了一个未命名的非静态数据成员。 The declaration order of these members is unspecified.这些成员的声明顺序未指定。 The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise .如果实体是对对象的引用,则此类数据成员的类型被引用类型,如果实体是对函数的引用,则是对被引用函数类型的左值引用,否则是对应的捕获实体的类型 A member of an anonymous union shall not be captured by copy.匿名工会的成员不得被复制。

cpprefence worded it better: cpprefence措辞更好:

The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as lvalue references to the referenced functions, and references to objects are captured as copies of the referenced objects ).每个数据成员的类型是对应的捕获实体的类型,除非实体具有引用类型(在这种情况下,对函数的引用被捕获为对被引用函数的左值引用,而对对象的引用被捕获为引用的对象)。

Perhaps this helps clarify what I think you're confused about:也许这有助于澄清我认为你对什么感到困惑:

template <typename T> void f(T arg) { }

int x = 10;
int& r = x;

auto y = r;     // y is int (copied value from reference)
f(r);           // T in f<T>() is deduced to int, arg in f() is int

In both cases if you want the result to be a reference, you must say so:在这两种情况下,如果您希望结果作为参考,则必须这样说:

template <typename T> void f(T& arg) { }

int x = 10;
int& r = x;

auto& y = r;     // y is reference-to-int
f(r);            // T in f<T>() is int, arg in f is ref-to-int

Similarly, in your code:同样,在您的代码中:

AClass a;
AClass& aRef = a;

[=]() { return aRef.member; }; // "Attempting to reference a deleted function"

The captured aRef is an attempted COPY of the local variable from a reference to a different object.捕获的 aRef 是尝试从对不同对象的引用复制局部变量。 using [=] says to copy by value, and it does not read this as "oh, the source is a reference, so I'm going to copy the reference by value and store the reference in a reference."使用 [=] 表示按值复制,它不会将其读作“哦,源是引用,所以我将按值复制引用并将引用存储在引用中。” It actually says, "If the source type has reference qualifiers, ignore the and consider what's left. You want to copy by value? Ok, I'll copy an AClass into a new variable. Oh wait... can't. Sorry."它实际上说,“如果源类型有引用限定符,忽略 并考虑剩下的。你想按值复制吗?好的,我将一个 AClass 复制到一个新变量中。哦等等......不能。抱歉.”

What you want is:你想要的是:

[&]() { return aRef.member; };

Or more specifically:或者更具体地说:

[&aRef]() { return aRef.member; };

That tells the captured type that it should be a reference.这告诉捕获的类型它应该是一个引用。 The source type is not as important as the destination type in cases like this.在这种情况下,源类型不如目标类型重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM