lambda fct返回参考

Ste*_*fan 7 c++ lambda c++11

我努力使lambda函数通过引用返回值,而不复制引用的值.我下面的代码示例说明了问题.它编译并运行正常,但使用"//"注释行而不是上面的行,它不会.我找到了两个解决方法(在我的示例中都说明了):

  • 用std :: ref()包装结果
  • 返回指针而不是引用

但两种解决方法都不是我真正想要的,我不明白为什么它们是必要的:表达式"makeRefA()"已经是lambda函数返回的类型(const A&),因此既不能复制也不能转换.顺便说一句:当我没有明确地删除它时(在我的"真实"代码中是性能问题),真正调用了复制构造函数.对我来说,它看起来像编译器错误,但我已经尝试了几个C++ 11编译器,它们都显示相同的错误.那么lambda函数中的"return"语句有什么特别之处吗?

#include <functional>
#include <iostream>

struct A {
  A(int i) : m(i) { }
  A(const A&) = delete;
  int m;
};

void foo(const A & a) {
  std::cout << a.m <<'\n';
}

const A & makeRefA() {
  static A a(3);
  return a;
}

int main() {
  std::function<const A&()> fctRef = [&]
    { return std::ref(makeRefA()); }; //compiles ok
    //{ return makeRefA(); }; //error: use of deleted function 'A::A(const A&)'
  foo(fctRef());

  std::function<const A*()> fctPtr = 
    [&] { return &makeRefA(); };
  foo(*fctPtr());

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

3
3
Run Code Online (Sandbox Code Playgroud)

Sha*_*ang 7

您可以指定返回类型

#include <functional>
#include <iostream>

struct A {
    A(int i) : m(i) { }
    A(const A&) = delete;
    int m;
};

void foo(const A & a) {
    std::cout << a.m <<'\n';
}

const A & makeRefA() {
    static A a(3);
    return a;
}

int main() {
    std::function<const A&()> fctRef = [&]()->const A&
//    { return std::ref(makeRefA()); }; //compiles ok
    { return makeRefA(); }; // works
    foo(fctRef());

    std::function<const A*()> fctPtr =
    [&] { return &makeRefA(); };
    foo(*fctPtr());

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Aar*_*aid 7

默认情况下,lambda的自动推导类型是类型的非引用版本

...返回类型是返回表达式的类型(在左值到右值,数组到指针或函数到指针隐式转换之后); (资源)

如果您想要一个带引用的返回类型,则必须更明确地指定它.以下是一些选项:

[&]()
-> decltype( makeRefA() )
{ return makeRefA()); };
Run Code Online (Sandbox Code Playgroud)

或者只是完全明确返回类型 ->

[&]()
-> const A&
{ return makeRefA(); }
Run Code Online (Sandbox Code Playgroud)

如果使用C++ 14,那么只需使用decltype(auto),

[&]()
-> decltype(auto)
{ return makeRefA(); }
Run Code Online (Sandbox Code Playgroud)

规则decltype有时可能很复杂.但事实makeRefA()是表达式(而不是简单地命名变量)意味着表达式(const A&)的类型忠实地返回decltype( makeRefA() ).