我正在观看Jason Turner关于IIFE的谈话。有一个示例看起来像下面的代码:
#include <iostream>
#define EOL '\n'
using std::cout;
class C
{
public:
C(){ std::cout << "Def ctor\n"; }
C(const C &c){ std::cout << "Copy ctor\n" << EOL; }
C(C&& c){ std::cout << "Move ctor\n" << EOL; }
~C(){ std::cout << "Dtor\n"; }
void Print() const { cout << "address: " << this << EOL; }
};
int main()
{
C c;
c.Print();
const auto &refc = [&](){
cout << "lambda returns..." << EOL;
return c; }();
refc.Print();
return 0;
}
输出为:
Def ctor
address: 0x7ffe6a6765bf
lambda returns...
Copy ctor
address: 0x7ffe6a6765be
Dtor
Dtor
这表明返回值正在使用copy构造函数,而将返回值定义为const引用,并创建一个新复制的对象以返回const引用。
但是如果lambda定义为:
const auto &refc = [&]()->const auto&{
cout << "lambda returns..." << EOL;
return c; }();
没有调用副本ctor,结果为:
Def ctor
address: 0x7fff319dc2af
lambda returns...
address: 0x7fff319dc2af
Dtor
我认为无需复制,设计背后是否有充分的理由?我想知道在什么情况下复制捕获的变量有用吗?
答案 0 :(得分:1)
lambda上的文档告诉我们,如果未未指定尾随返回类型,则lambda的返回类型是什么:
省略的尾随返回类型:闭包
operator()
的返回类型是从返回语句推导出的,就好像其返回类型声明为auto
。
因此它导致复制构造函数被调用。
如果要防止这种情况,可以将auto&
或const auto&
用作尾随返回类型。