如果我将可变 lambda 作为 const 引用传递给函数,会发生什么?

Shu*_*Guo 3 c++ lambda c++11 c++14 c++17

当我将可变 lambda 作为 const 引用传递时,代码实际上会做什么?

为什么编译器不引发错误,这是一个未定义的操作吗?

std::function<void()>为什么f1和f2使用的f1和f2使用的不同auto?

我发现了一个类似的问题,但我仍然不完全明白

const std::function 包装非常量运算符() / 可变 lambda

#include <iostream>
#include <functional>

void call(std::function<void()> const & cb) {
    cb();
    cb();
}

int main() {
    std::function<void()> f1 = [a = 0] () mutable {
        std::cout << ++a << std::endl;
    };
    call(f1); // prints 1 2
    call(f1); // prints 3 4

    auto f2 = [a = 0] () mutable {
        std::cout << ++a << std::endl;
    };
    call(f2); // prints 1 2
    call(f2); // prints 1 2
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/765endY7c

Mar*_*k R 5

在第一种情况下,两个调用都call(f1)使用相同的实例std::function<void()>。

在第二种情况下,call(f2);隐式转换形式 lambda 开始std::function<void()>启动,并创建相应的临时对象。因此第二次调用使用临时对象的新副本。

尝试在 cppinsights 中转换此代码以查看更多详细信息。

int main()
{
    
  class __lambda_10_32
  {
    public: 
    inline /*constexpr */ void operator()()
    {
      std::cout.operator<<(++a).operator<<(std::endl);
    }
    
    private: 
    int a;
    public: 
    // inline /*constexpr */ __lambda_10_32(const __lambda_10_32 &) noexcept = default;
    // inline /*constexpr */ __lambda_10_32(__lambda_10_32 &&) noexcept = default;
    __lambda_10_32(const int & _a)
    : a{_a}
    {}
    
  };
  
  std::function<void ()> f1 = std::function<void ()>(__lambda_10_32{0});
  call(f1);
  call(f1);
    
  class __lambda_16_15
  {
    public: 
    inline /*constexpr */ void operator()()
    {
      std::cout.operator<<(++a).operator<<(std::endl);
    }
    
    private: 
    int a;
    public: 
    // inline /*constexpr */ __lambda_16_15(const __lambda_16_15 &) noexcept = default;
    // inline /*constexpr */ __lambda_16_15(__lambda_16_15 &&) noexcept = default;
    __lambda_16_15(const int & _a)
    : a{_a}
    {}
    
  };
  
  __lambda_16_15 f2 = __lambda_16_15{0};
  call(std::function<void ()>(__lambda_16_15(f2)));
  call(std::function<void ()>(__lambda_16_15(f2)));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)