【问题标题】:Why does a variable become 'const' when I use a [=] capture (using Lambda class)?当我使用 [=] 捕获(使用 Lambda 类)时,为什么变量会变为“const”?
【发布时间】:2016-08-21 13:56:20
【问题描述】:

前提#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]() 

但实际上我并不太明白为什么会收到该错误。

【问题讨论】:

  • 我希望这是程序中定义的所有对象的默认行为:默认情况下const,添加mutable来更改它。

标签: c++ multithreading opencv lambda


【解决方案1】:

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

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

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

【讨论】:

  • 加一个是因为你说明了真正的原因:即被拷贝捕获的值不会存储为const而是调用operator()const成员函数除非lambda被定义作为mutable
【解决方案2】:

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

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

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

[foo]()
mutable {

   // Lambda can modify foo, but it's a copy of the original
   // captured variable
}

【讨论】:

  • 值得注意的是,复制到那里的对象(一个 OpenCV 矩阵)是一个指向实际数据的共享指针。可变 lambda 仍会修改基础数据。
猜你喜欢
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2013-11-06
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多