【问题标题】:C++ Why the compiler is not able to generate code that returns const reference of a captured variable in LambdaC++ 为什么编译器无法生成返回 Lambda 中捕获变量的 const 引用的代码
【发布时间】:2019-07-02 07:22:11
【问题描述】:

我正在观看 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

这说明返回值使用了拷贝构造函数,而返回值被定义为一个const引用,并创建了一个新复制的对象返回到这个const引用。

但如果 lambda 定义为:

const auto &refc = [&]()->const auto&{ 
    cout << "lambda returns..." << EOL;
    return c; }();

没有调用复制ctor,结果是:

Def ctor
address: 0x7fff319dc2af
lambda returns...
address: 0x7fff319dc2af
Dtor

我认为文案没有必要,设计背后有充分的理由吗?我想知道在什么情况下复制捕获的变量有用?

【问题讨论】:

  • 我的错误,已编辑,对混乱感到抱歉
  • Lambda 返回的行为就像声明为auto
  • 如果要引用返回可以返回auto&amp;

标签: c++ lambda


【解决方案1】:

lambda 上的文档告诉我们,如果尾随返回类型指定,则 lambda 的返回类型是什么:

省略 trailing-return-type:闭包的 operator() 的返回类型是从 return 语句中推导出来的>.

所以它导致复制构造函数被调用。

如果您想防止这种情况,您可以使用auto&amp;const auto&amp; 作为尾随返回类型。

【讨论】:

  • 但是 lambda 的返回类型是 const auto&amp; 而不是 auto
  • @r0ng:你为什么认为是const auto&amp;。你有什么可以这么说的参考吗?
猜你喜欢
  • 2017-02-03
  • 2013-11-06
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2013-11-08
相关资源
最近更新 更多