C++ 如何从lambda函子';谁的身体?

C++ 如何从lambda函子';谁的身体?,c++,c++11,lambda,c++14,C++,C++11,Lambda,C++14,我试图从lambda表达式中增加一个局部变量: #include <iostream> template<typename T> T foo(T t){ T temp{}; [temp]() -> void { temp++; }(); return temp; } int main() { std::cout<< foo(10) << std::endl; } #包括 模板

我试图从lambda表达式中增加一个局部变量:

#include <iostream>

template<typename T>
T foo(T t){
    T temp{};
    [temp]() -> void { 
        temp++; 
    }();
    return temp;
}

int main()
{
    std::cout<< foo(10) << std::endl;
}
#包括
模板
T-foo(T-T){
T温度{};
[temp]()->void{
temp++;
}();
返回温度;
}
int main()
{

std::cout
temp
在不可变lambda中通过复制捕获时,无法修改

您可以通过引用捕获
temp

template<typename T>
T foo(T t){
    T temp{};
    [&temp]() -> void { 
        temp++; 
    }();
    return temp;
}
模板
T-foo(T-T){
T温度{};
[&temp]()->void{
temp++;
}();
返回温度;
}

如果要按值捕获变量并对其进行修改,则需要标记lambda
可变值

[temp]() mutable -> void {
//       ^^^^^^^ 
    temp++; 
}();
这允许主体修改由值捕获的参数,并调用它们的非常量成员函数

您所说的“局部变量”有点含糊不清

  • 要增加
    foo
    temp
    ,您需要这样做,因此您的lambda将如下所示:
    [&temp]{temp++;}
  • 要增加lambda的
    temp
    ,您需要这样做,使lambda看起来像:
    [temp]()可变{temp++;}
  • 您似乎不太可能尝试执行2,因为您所做的任何更改都将在lambda返回时丢失,因为它不会返回任何内容。并且,在您给出的示例中,您不会在lambda中进一步使用
    temp

    因此,假设您试图执行1,您需要确保
    T
    不是引用,也不是
    const
    。以下任一示例都会给您带来麻烦:

    const auto t = 1;
    foo(t);
    

    为了避免这两种情况,您应该使用以下内容定义
    foo
    temp

    衰变温度{};
    
    它是C++14,因此您可以简化lambda。
    也就是说,这些是一些有效的解决方案(我假设您希望更改原始变量的值,而不是它的副本的值):

    • 通过引用捕获:

      template<typename T>
      T foo(T t){
          T temp{};
          [&temp]() -> void { 
              temp++; 
          }();
          return temp;
      }
      
      [&temp](){temp++;}();

    (您必须保证
    temp
    的寿命与lambda的寿命相同)

    • 来回复制:

      temp=[temp=temp]()可变{return++temp;}();

    (不要求您保证
    temp
    的寿命与lambda的寿命相同)

    • 来回移动:

      temp=[temp{std::move(temp)}]()可变{temp++;返回std::move(temp);}();

    (不要求您保证
    temp
    的寿命与lambda的寿命相同)


    等等…

    它会修改复制的一个,而与外部的
    temp
    无关吗?@songyuanyao:是的。:-@songyuanyao是的,它仍然是一个附带的值捕获,不管它的易变性如何。我明白了,谢谢。也许更值得一提的是,我认为它与OP的初衷相冲突。看到有人使用C,我很高兴++14的捕获初始值设定项,所以有一个+1。但是由于lambda的使用方式,我认为这里不需要C++11语法以外的任何东西。@JonathanMee我知道,你是对的,但这是一个使用它们的好机会!!:-)老实说,我想要C++14给我们的是在捕获列表中定义临时值的能力,比如
    [int i{}]{return++i;}
    虽然已经讨论过了,但它在C++17中仍然不可用:(@JonathanMee为什么不能在lambda的主体中定义它们呢?我不完全理解这一点,抱歉…@JonathanMee:FWIW,
    [i=int{}])可变的{return i;}
    工作得很好。例如,我觉得我没有领会你的意思;-]
    auto& t = bar;
    foo(t);
    
    decay_t<T> temp{};