2013-09-26 14 views
14
std::function<int()> void f1() 
{ 
    int a, b, c, d, ..., x, y, z; 

    return [=] { return a + b + c; }; 
} 

vs.Czy złym zwyczajem jest zawsze uchwycić wszystko w wyrażeniu lambda?

std::function<int()> void f2() 
{ 
    int a, b, c, d, ..., x, y, z; 

    return [a, b, c] { return a + b + c; }; 
} 

trzeba dodawać, że ta pierwsza jest krótsza, bardziej poręczne i bardziej elegancki niż ten ostatni.

Ja jednak nadal martwić:

Z punktu widzenia wydajności, to ten ostatni zawsze lepiej niż poprzednio?

Czy standard gwarantuje, że wyrażenie lambda przechwyci tylko niezbędne zmienne? W pierwszym przykładzie przechwytywane są tylko a, b, c niewykorzystane zmienne d, ..., x, y, z nie są.

+2

Przechwytują tylko to, co jest używane. Styl przebija wydajność przez długie ujęcie tutaj. – chris

+0

@chris, czy możesz skierować mnie do standardu? – xmllmx

+3

@xmllmx Nie mogę skierować cię do akapitu, ale rozważ klasę, która ma konstruktora kopii z efektami ubocznymi (zapis pliku, cout itd.). Jeśli lambda przechwyciła nieużywany, niepubliczny obiekt tego typu według wartości i dlatego wywołał konstruktora kopiowania, byłby on * całkiem zły *. Więc nawet nie widząc "prawa" w tej sprawie, powiedziałbym, że jest to całkiem pewne. – us2012

Odpowiedz

18

Standard gwarantuje, że w przypadku domyślnego przechwytywania jedynymi zmiennymi, które zostaną przechwycone przez domyślne przechwytywanie z otaczającego środowiska, są te, które są używane w lambda.

Jako takie, określanie poszczególnych zmiennych do przechwytywania działa jako dokumentacja tego, czego się spodziewasz, ale nigdy nie powinno wpływać na wydajność.

Dla każdego, kto dba, dokładna treść od normy jest (§5.1.2/11, 12):

11 Jeżeli lambda wyrażenie ma skojarzony capture-default i jego związek-oświadczenie odr-uses (3.2) this lub zmienna z automatycznym czasem przechowywania, a jednostka wykorzystująca odr nie jest jawnie przechwytywana, wtedy jednostka odr używana jest domyślnie przechwytywana; takie podmioty są deklarowane w ramach zakresu wyrażenia lambda. [] Notatka rozliczona]

12 Jednostka zostaje przechwycona, jeśli jest przechwycona jawnie lub niejawnie. [...]

Podsumowanie: niejawna Szczegółowy wychwytujący ([=] lub [&]) uchwycą tylko zmienne, które są stosowane w lambda.

1

Niezupełnie ... większość innych języków nie wymaga (ani nawet nie zezwala) na określenie, co chcesz przechwycić.

Pozwól kompilatorowi wywnioskować, co jest konieczne, kiedy może.
To się nie pomyli i nie "przypadkowo" zrobi czegoś nieużywanego w lambda.
Jeśli chcesz być wyraźny (czasami ma to sens), to właśnie do tego służą tradycyjne funktory.

0

Semantydycznie powinieneś importować te zmienne, które faktycznie potrzebujesz, do zakresu twojej lambda. W przypadku innych typów niż wbudowane prawdopodobnie będziesz chciał również przechwytywać przez odniesienie.

+1

Jeśli wyrażenie lambda jest wynikiem do zwrócenia, przechwytywanie zmiennych przez odniesienie jest w większości przypadków kiepską praktyką. – xmllmx

+0

@xmllmx: Nie wiem, jaki aspekt tej odpowiedzi próbujesz poprawić ... nie jest to po prostu "zła praktyka", gdy zwraca się lambdę; to jest niewłaściwe. W takim przypadku powinno być oczywiste, że nie powinieneś przechwytywać go przez odniesienie, ponieważ kod nie zadziała. Porada udzielona w tej odpowiedzi jest całkiem na znak ... "uchwycenie przez odniesienie, gdy to możliwe". – Mehrdad

+0

@Mehrdad, jeśli wyrażenie lambda odwołuje się do zmiennej statycznej, nie jest ono błędne, nawet jeśli jest to wynik do zwrócenia. – xmllmx

Powiązane problemy