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

Rad*_*oga 12 c++ lambda multithreading opencv

前提#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);
}
Run Code Online (Sandbox Code Playgroud)

编译器返回此错误

错误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);
Run Code Online (Sandbox Code Playgroud)

我解决了这个错误,取代了这一行

auto var = [=]()
Run Code Online (Sandbox Code Playgroud)

有了这个

auto var = [=, &input_img, &output_img]() 
Run Code Online (Sandbox Code Playgroud)

但实际上我并不深刻理解为什么我收到了这个错误.

JVA*_*pen 12

如果你在lambda中按值捕获,你将获得一个存储的"成员".由于默认值operator()是const函数,因此无法修改它们.

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

通过引用捕获值,您有一些行为类似于指向非const对象的const指针,因此如果没有可变,您可以调整这些对象.(除非他们已经在const)

  • 另外一个是因为你说明了真正的原因:也就是说,复制值捕获不会存储为`const`而是调用`operator()`是`const`成员函数,除非`lambda`被定义为`mutable`. (5认同)

Sam*_*hik 9

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

[foo]()
{
   // foo, whatever that is, is const
}
Run Code Online (Sandbox Code Playgroud)

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

[foo]()
mutable {

   // Lambda can modify foo, but it's a copy of the original
   // captured variable
}
Run Code Online (Sandbox Code Playgroud)