2015-07-02 10 views
13

Buduję funkcję lambda, która wymaga dostępu do dużej liczby zmiennych w kontekście.Przekazywanie przez stałe odniesienie na liście przechwytywania lambda

const double defaultAmount = [&]{ 
    /*ToDo*/ 
}(); 

Wolałbym nie używać [=] w wykazie jako nie chcę wiele kopii wartości mają być wykonane.

Obawiam się stabilności programu, jeśli używam [&], ponieważ nie chcę, aby lambda modyfikowała przechwytywanie zestawu.

Czy mogę przejść przez odniesienie do const? [const &] nie działa.

Być może dobry kompilator optymalizuje wartościowe kopie, dlatego najlepiej jest użyć [=].

+0

Czy są to zmienne lokalne lub członkowskie? Z jakiego kompilatora korzystasz? – MikeMB

+0

Trochę z obu. Używam MSVC2012 i mam napisać kod kompilujący się z nowszym g ++. –

Odpowiedz

11

Można tworzyć i uchwycić odniesienia const wyraźnie:

lista
int x = 42; 
const int& rx = x; 
auto l = [&rx]() { 
    x = 5; // error: 'x' is not captured 
    rx = 5; // error: assignment of read-only reference 'rx' 
}; 
2

Niestety gramatyka C++ 11 na to nie pozwala, więc nie.

+0

Jeśli podprogram wymaga "sporej liczby zmiennych w kontekście", wykonanie właściwej funkcji i przekazanie jej wszystkich jest prawdopodobnie dokładnie tym, czego OP stara się uniknąć. – Angew

2

Można uchwycić stałą referencję do obiektu, a nie sam obiekt:

A a; 
const A& ref_a = a; 

const double defaultAmount = [&]{ 
    ref_a.smth(); 
}(); 
7

Wychwytywanie jest ograniczona, co może zostać złapanym; w zasadzie by-value lub by-reference (o nazwie lub domyślnie), wskaźnik this i nic.

Od cppreference;

capture-lista - lista oddzielonych przecinkami zero lub więcej zrzutów, ewentualnie początek z przechwytywania domyślny. lista przechwytywania mogą być przekazywane w następujący sposób (patrz poniżej szczegółowym opisie):

  • [a,&b] gdzie a zostaje schwytany przez wartość i b zostaje schwytany przez odniesienie.
  • [this] oddaje wskaźnik this wartością
  • [&] przechwytuje wszystkie zmienne automatyczne ODR używanych w organizmie lambda przez odniesienie
  • [=] przechwytuje wszystkie zmienne automatycznych ODR użyty w korpusie lambda według wartości
  • [] nic nie przechwytuje

Możesz utworzyć lokalny const& dla wszystkich obiektów, które chcesz przechwycić i użyć ich w lambda.

#include <iostream> 

using namespace std; 

int main() 
{ 
    int a = 5; 
    const int& refa = a; 
    const int b = [&]() -> int { 
     //refa = 10; // attempts to modify this fail 
     return refa; 
    }(); 
    cout << a << " " << b << endl; 
} 

Wychwycenie może dotyczyć wszystkich odniesień lub jawnej listy, która jest wymagana;

const int b = [&refa]() 

Inną alternatywą nie jest uchwycenie zmiennych lokalnych w ogóle. Następnie tworzysz lambdę, która przyjmuje jako argumenty zmienne, których potrzebujesz. Może to wymagać więcej wysiłku, gdy rośnie liczba zmiennych lokalnych, ale masz większą kontrolę nad tym, jak lambda akceptuje jej argumenty i jest w stanie korzystać z danych.

auto lambda = [](const int& refa /*, ...*/) { */...*/ } 
lambda(...); 
Powiązane problemy