如果从lambda表达式生成的类没有默认的ctor,那么如何创建该生成类类型的对象
我正在使用列出的资源在这里学习C ++。特别是,我在Lippman的C ++底漆中阅读了有关 lambda表达式。在那里,我知道lambdas是功能对象。此外,lambda表达式产生的类没有默认构造函数。因此,请例如:
auto wc = find_if(words.begin(), words.end(),
[sz](const string &a){
return s.size() >= sz;
};
写的是,上面的lambda表达式将生成一个看起来像类似的类:
class SizeComp {
SizeComp(size_t n): sz(n) { } // parameter for each captured
variable
// call operator with the same return type, parameters, and body as the lambda
bool operator()(const string &s) const
{ return s.size() >= sz; }
private:
size_t sz; // a data member for each variable captured by value
};
因此,发生的是该编译器生成类的未命名对象,并将第三个参数作为第三个参数传递给>
> std :: find_if
上面显示的。我能理解。
现在,我的思考/理解是,由于该编译器生成的类没有默认的ctor,因此第三个参数传递给std :: find_if
不得使用默认CTOR创建,因为这将失败,因此。因此,在内部,应使用参数化的ctor创建传递的对象,例如:
auto wc = find_if(words.begin(), words.end(), SizeComp(sz)); //note the third argument uses the parameterized ctor
我的第一个问题是,因为在空捕获列表的情况下没有默认的ctor in C ++ 11 ,那么该编译器的对象如何生成类的对象被创建。我的意思是,如果是空捕获列表,则在编译器生成的类中不会有数据成员,因此不会有参数化的CTOR。这意味着该编译器生成的类既没有默认值也没有参数化的CTOR。那么如何生成此类的对象。例如,当捕获列表为空时,下面显示的情况将无法正常工作:
auto wc = find_if(words.begin(), words.end(),
[](const string &a){ //NOTE THE CAPTURE LIST IS EMPTY
return s.size() >= 5;
};
现在,创建第三个参数到std :: find_if
:
auto wc = find_if(words.begin(), words.end(), CompGeneratedClass()); //this can't work because there is no default ctor
我也知道对于普通/普通用户 - 定义的类,如果我们提供用户定义的CTOR,则编译器将不会为该类生成默认的CTOR。因此,在我看来,由于在空捕获列表lambda表达式中没有用户定义的ctor,因此编译器应为此编译器生成的类生成默认的CTOR。但是C ++标准表示不会有默认的CTOR。因此,我的第二个问题是,为什么此编译器生成的类具有与用户定义的类不同的行为。
另外,请注意,这种解释不仅限于Lippman的C ++底漆。我在
I am learning C++ using the resource listed here. In particular, i read about lambda expressions in C++ Primer by Lippman. There i came to know that lambdas are function objects. Moreover, classes generated from lambda expressions do not have a default constructor. So take for example:
auto wc = find_if(words.begin(), words.end(),
[sz](const string &a){
return s.size() >= sz;
};
It is written that the above lambda expression will generate a class that will look something like:
class SizeComp {
SizeComp(size_t n): sz(n) { } // parameter for each captured
variable
// call operator with the same return type, parameters, and body as the lambda
bool operator()(const string &s) const
{ return s.size() >= sz; }
private:
size_t sz; // a data member for each variable captured by value
};
So what happens is that an unnamed object of this compiler generated class is created and is passed as the third argument to the std::find_if
shown above. I can understand this.
Now it is my thinking/understanding that since this compiler generated class has no default ctor, so the third argument that is passed to the std::find_if
must not be created using a default ctor since that would fail. So, internally the object that is passed should be created using the parameterized ctor something like:
auto wc = find_if(words.begin(), words.end(), SizeComp(sz)); //note the third argument uses the parameterized ctor
My first question is that since there is no default ctor in case of an empty capture list in C++11, so how will an object of that compiler generated class be created. I mean in case of an empty capture list, there will be no data members inside the compiler generated class so there will be no parameterized ctor. Which means that this compiler generated class has neither default nor parameterized ctor. Then how can an object of this class be generated. For example, the situation shown below won't work when the capture list is empty:
auto wc = find_if(words.begin(), words.end(),
[](const string &a){ //NOTE THE CAPTURE LIST IS EMPTY
return s.size() >= 5;
};
Now, how will the third argument to std::find_if
be created:
auto wc = find_if(words.begin(), words.end(), CompGeneratedClass()); //this can't work because there is no default ctor
I also know that for a normal/ordinary user-defined class if we provide a user-defined ctor, then the compiler will not generate a default ctor for that class. So, it seems to me that since in case of an empty capture list lambda expression there is no user-defined ctor, the compiler should generate a default ctor for this compiler generated class. But the C++ standard says that there won't be a default ctor. So my second question is that why does this compiler generated class has different behavior than an user-defined class.
Also, note that this explanation is not only limited to C++ Primer by Lippman. I've seen the same explanation in CppCon presentations as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的问题是思想框架。虽然底漆正在以很容易理解的方式解释行为,但实际上不应从字面上采取行为。
规范文本描述了行为,而不是实现行为的方法。编译器实际上不需要以相同的方式创建类。
例如,供应商总是可以将某个秘密标签潜入构造函数的参数列表中。想象一下,这就是它产生的:
我们不能命名该标签,甚至不知道它的存在,因此我们无法在另一行上创建lambda。而且,该类将永远不会有默认构造函数。那是的方法。但是即使那样,编译器也不必这样做。
该实施不受与我们相同的规则的约束;只要该程序正确翻译,该标准就会为实施提供巨大的余地。编译器可以保佑一个字节,并说“这是lambda”,无需打电话给构造函数。为什么?!因为它完成了标准所说的内容;可观察到的行为是完整的(考虑一下,可以通过C ++程序观察到无捕获的lambda的初始化吗?)
有时实现需要“作弊”;赫克,众所周知,实现将调用私人构造函数以完成工作。但这并不是真正的作弊,因为相同的规则不适用。
The problem here is that of frame of mind. While the Primer is explaining the behavior in ways that one could easily understand, it is not to be taken literally.
The normative text describes behavior, not ways to achieve it. A compiler doesn't actually need to create a class the same way we do.
For instance, a vendor can always sneak in some secret tag into the constructor's parameter list. Imagine this is what it generates:
We can't name that tag or even know of its existence, so we can't create the lambda on another line. And the class will never have a default constructor. That's a way to do it. But even then, a compiler doesn't have to do that.
The implementation is not bound by the same rules as us; the standard gives great leeway to implementations, so long as the program is translated correctly. A compiler could just bless a byte and say "this is a lambda", no need to call a constructor. Why?! Because it accomplishes what the standard says; the observable behavior is intact (think about it, can the initialization of a capture-less lambda be observed by a C++ program?)
Sometimes implementations need to "cheat"; heck, it's been known that implementations will call private constructors to get the job done. But it's not really cheating, because the same rules do not apply.