2016-08-21 11 views
12

Przesłanka # 1: Już rozwiązałem ten błąd, ale nie zrozumiałem głęboko przyczyny błędu kompilatora.Dlaczego zmienna staje się "stała", gdy używam [=] przechwytywania (przy użyciu klasy Lambda)?

Przesłanka # 2: Celem tego programu jest skopiowanie obrazu na inny obraz w procesie wielowątkowym. Być może istnieje lepszy sposób, ale nie jest to główny temat pytania (patrz założenie nr 1).

Napisałem prosty program przy użyciu biblioteki OpenCV 3.1, aby skopiować obraz do innego obrazu. Wykorzystuje wszystkie rdzenie procesora wykorzystując więcej wątków.

Kod jest:

#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); 
} 

kompilator zwróci mi ten błąd

Błąd void copy_image C2664”(const cv :: Mat &, cv :: Mat &, int, int) „: nie można przekonwertować argumentu 2 z 'const cv :: Mat' do 'cv :: Mat &'

że reffers ten wiersz kodu:

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

I rozwiązać ten błąd, zastępując ten wiersz

auto var = [=]() 

z tym

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

ale faktycznie nie głęboko zrozumieć dlaczego dostałam że błąd.

+0

Chciałbym, aby było to domyślne zachowanie dla _all_ obiektów zdefiniowanych w programie: 'const' domyślnie, dodaj' zmienny', aby go zmienić. – isanae

Odpowiedz

12

Jeśli do przechwytywania przez wartość w lambda, otrzymasz "członka", który zostanie zapisany. Ponieważ domyślna operator() jest funkcją const, nie można ich modyfikować.

Lambdas można zdefiniować jako []() mutable {}, aby umożliwić modyfikowanie zmiennych lokalnych.

Przez przechwycenie wartości przez odniesienie, masz coś, co zachowuje się jak wskaźnik const dla obiektu nie będącego stałym, więc bez zmiennego możesz dostosować te obiekty. (Chyba że już tam, gdzie stały)

+4

Plus jeden, ponieważ ilustrujesz prawdziwy powód: oznacza to, że przechwycone przez wartości kopiowania nie są przechowywane jako 'const', ale raczej wywołanie' operator() 'jest funkcją' const', chyba że 'lambda' jest zdefiniowana jako 'zmienna'. – 101010

8

Przechwycone zmienne są rzeczywiście const w zakresie Lamba:

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

w A zmienny lambda, złapanych zmienne nie są stałe:

[foo]() 
mutable { 

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

Warto zauważyć, że skopiowany tam obiekt (macierz OpenCV) jest współdzielonym wskaźnikiem do danych rzeczywistych. Zmienna lambda nadal modyfikowałaby dane bazowe. – Sam

Powiązane problemy