了解 Lambda 闭包类型如何删除默认构造函数

2021-12-23 00:00:00 constructor lambda default c++

从 5.1.2 开始

<块引用>

[19] 与 lambda 表达式关联的闭包类型具有已删除的 (8.4.3) 默认构造函数 和已删除的复制赋值运算符.它有一个隐式声明的复制构造函数(12.8)并且可能有一个隐式声明的移动构造函数(12.8).[注意:复制/移动构造函数以相同的方式隐式定义因为任何其他隐式声明的复制/移动构造函数都将被隐式定义.――结尾说明]

我正在阅读 C++ Primer 14.8.1,它解释了编译器将 lambda 表达式转换为未命名类的未命名对象.如果删除默认构造函数,我如何定义不包含 lambda 捕获的 lambda 函数的对象?

 auto g = [](){};

这在概念上与...不一样吗

 类 lambdaClass{上市:lambdaClass() = 删除;lambdaClass&运算符=(const lambdaClass&)=删除;空操作符()(){ }//复制/移动隐式定义的构造函数和析构函数};汽车 g = lambdaClass();//会是一个错误,因为默认值被删除了.

如果存在捕获,则将定义一个构造函数其他而不是默认构造函数,并且可以初始化此类对象(只要传递了参数).但是如果没有捕获并删除默认构造函数,那么可以创建一个 lambda 类对象在概念上似乎并不一致.

嗯,也许 lambda 类根据其 lambda 捕获创建构造函数的概念是没有根据的,尽管 C++ Primer 中是这样描述的(我在标准中找不到它的引用),因为以下代码确实即使我从概念上期望它也不起作用:

int sz = 2;汽车 a = [sz](){ 返回 sz;};声明类型(a)b(10);//编译错误decltype(a) b = a;//虽然一切都很好

解决方案

closure 到 lambda 的关系类似于 object 到班级.

C++11 标准说闭包!类型没有默认构造函数,这是正确的,因为它没有说它没有构造函数.

lambda 用于创建闭包.但是您引用的段落将针对 C++14 更改.

ClosureType() = delete;//(直到 C++14)ClosureType(const ClosureType&) = default;//(C++14 起)ClosureType(ClosureType&&) = 默认值;//(C++14 起)

<块引用>

闭包类型不是DefaultConstructible.闭包类型具有 a 删除(C++14 前) no(C++14 起) 默认构造函数.复制构造函数和移动构造函数被隐式声明(C++14 前) 声明为默认(C++14 起) 并且可以根据复制构造函数和移动构造函数的常用规则.

http://en.cppreference.com/w/cpp/language/lambda

From 5.1.2

[19] The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deleted copy assignment operator. It has an implicitly-declared copy constructor (12.8) and may have an implicitlydeclared move constructor (12.8). [ Note: The copy/move constructor is implicitly defined in the same way as any other implicitly declared copy/move constructor would be implicitly defined. ―end note ]

I'm reading through C++ Primer 14.8.1 which explains lambda expressions being translated by the compiler in to an unnamed object of an unnamed class. How is it I can I define objects of lambda functions which do not contain a lambda capture, if the default constructor is deleted?

 auto g = [](){};

Is this not conceptually the same as...

 class lambdaClass{
 public:
      lambdaClass() = delete;
      lambdaClass& operator=(const lambdaClass&) = delete;
      void operator()(){ }

      //copy/move constructor and destructor implicitly defined
};

auto g = lambdaClass(); //would be an error since default is deleted.

If there was a capture then a constructor other than the default constructor would be defined and it would be okay to initialise objects of such (as long as a parameter was passed). But if there is no capture and the default constructor is deleted, it doesn't seem consistent conceptually that a lambda class object can be created.

Edit: Hmm, maybe the conception that the lambda class creates constructors depending on its lambda captures is unfounded despite this being how it's described in C++ Primer (I can find no quote of it in the standard), because the following code does not work even though I would expect it to conceptually:

int sz = 2;
auto a = [sz](){ return sz;};
decltype(a) b(10); //compiler error
decltype(a) b = a; //all good though

解决方案

The relationship between a closure to lambda is similar to object to class.

The C++11 standard says that the closure! type has no default constructor, and that is correct because it doesn't say it has no constructor.

The lambda is used to create a closure. But your quoted parapgraph will change for C++14.

ClosureType() = delete;                     // (until C++14)
ClosureType(const ClosureType& ) = default; // (since C++14)
ClosureType(ClosureType&& ) = default;      // (since C++14)

Closure types are not DefaultConstructible. Closure types have a deleted (until C++14) no (since C++14) default constructor. The copy constructor and the move constructor are implicitly-declared (until C++14) declared as defaulted (since C++14) and may be implicitly-defined according to the usual rules for copy constructors and move constructors.

http://en.cppreference.com/w/cpp/language/lambda

相关文章