为什么当我使用 [=] 捕获(使用 Lambda 类)时变量变为"const"?

Why does a variable become 'const' when I use a [=] capture (using Lambda class)?

本文关键字:变量 const Lambda 使用 捕获 为什么      更新时间:2023-10-16

前提#1:我已经解决了错误,但是我没有深入了解编译错误的原因。

前提#2:这个程序的目标是通过多线程进程将一个图像复制到另一个图像中。也许存在更好的方法,但这不是问题的焦点(参见前提#1)。

我写了一个简单的程序,使用OpenCV 3.1库将一个图像复制到另一个图像。它利用了CPU的所有核心,使用了更多的线程。

代码是:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <thread>
using namespace cv;
using namespace std;
#define IMG_PATH "..\img\50a.png"

void copy_image(const Mat& input, Mat& output, int row_offset, int skip_row)
{
    cout << row_offset;
    Size size = input.size();
    for (int r = row_offset; r < size.height; r += skip_row)
    {
        for (int c = 0; c < size.width; c++)
        {
            output.at<Vec3b>(r, c) = input.at<Vec3b>(r, c);
        }
    }
}
int main()
{
    Mat input_img = imread(IMG_PATH);
    Mat output_img = Mat(input_img.size(), input_img.type()); output_img.setTo(255);
    vector<thread> threads;
    int thread_number = thread::hardware_concurrency();
    for (int i = 0; i < thread_number; i++)
    {
        cout << i;
        auto var = [=]() 
        {
            return copy_image(input_img, output_img, i, thread_number);
        };
        threads.push_back(thread(var));
    }
    for (auto& thread : threads) 
        thread.join();
    imshow("output_img", output_img);
    imwrite("result.png", output_img);
    waitKey(0);
}

编译器返回这个错误

错误C2664 'void copy_image(const cv::Mat &,cv::Mat &,int,int)':无法将参数2从'const cv::Mat'转换为'cv::Mat &'

表示它指的是这行代码:

return copy_image(input_img, output_img, i, thread_number);

我解决了替换这行

的错误
auto var = [=]()

auto var = [=, &input_img, &output_img]() 

但实际上我不太明白为什么会收到这个错误

如果您在lambda中按值捕获,您将获得一个被存储的'成员'。因为默认的operator()是const函数,所以不能修改。

Lambdas可以定义为[]() mutable {},以允许您修改局部变量。

通过引用捕获值,你得到了一些行为类似于指向非const对象的const指针的东西,所以没有可变对象,你可以调整这些对象。(除非它们已经是const)

捕获的变量确实是lamba范围内的const:

[foo]()
{
   // foo, whatever that is, is const
}

在可变lambda中,捕获的变量不是常量:

[foo]()
mutable {
   // Lambda can modify foo, but it's a copy of the original
   // captured variable
}