C ++ 11 lambdalar kullanmadıkları değişkenleri yakalar mı?


124

[=]Tüm yerel değişkenlerin bir lambda'daki değer tarafından yakalanmasını istediğimi belirtmek için kullandığımda , bu işlevdeki tüm yerel değişkenlerin kopyalanmasıyla mı yoksa sadece lambda tarafından kullanılan tüm yerel değişkenlerle mi sonuçlanır ?

Yani, örneğin, eğer sahipsem:

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i){ return my_measly_int + i; });

My_huge_vector, onu lambda'da kullanmasam bile kopyalanacak mı?

Yanıtlar:


115

Yakalama listesinde açıkça adlandırılan her değişken yakalanır. Varsayılan yakalama yalnızca (a) yakalama listesinde açıkça adlandırılmayan ve (b) lambda ifadesinin gövdesinde kullanılan değişkenleri yakalar . Değişken açıkça adlandırılmamışsa ve değişkeni lambda ifadesinde kullanmıyorsanız, değişken yakalanmaz. Örnekte, my_huge_vectorçekilmemiş.

C ++ 11 §5.1.2 [expr.prim.lambda] / 11 uyarınca:

Bir lambda ifadesinin ilişkili bir yakalama varsayılanı ve bileşik ifadesi odr kullanımları this veya otomatik depolama süresi olan bir değişkeni varsa ve odr kullanılan varlık açıkça yakalanmazsa, odr kullanılan varlığın örtük olarak yakalandığı söylenir.

Lambda ifadenizin ilişkili bir yakalama varsayılanı vardır: varsayılan olarak, değişkenleri değere göre yakalarsınız [=].

Yalnızca ve ancak bir değişken kullanılırsa ("kullanılmış" teriminin Tek Tanım Kuralı anlamında) örtük olarak yakalanan bir değişkendir. my_huge_vectorLambda ifadesinin gövdesinde ("bileşik ifade") hiç kullanmadığınız için, dolaylı olarak yakalanmaz.

§5.1.2 / 14 ile devam etmek için

Bir varlık kopya ile yakalanırsa

  • örtük yakalanır ve yakalama varsayılan olup =olmadığını veya
  • açık bir şekilde bir &.

Sizin my_huge_vector, dolaylı olarak yakalanmadığından ve açıkça yakalanmadığından, kopya veya referans yoluyla hiç yakalanmaz.


10
Kutsal bir Alıntı var mı?
GManNickG

Yine de, tüm ayrıntıları anlamak için §5.1.2'nin tamamının önemli olduğunu söyleyeceğim. Bu bölümde tanımlanmış birçok teknik terim vardır ve lambda ifadelerinin çeşitli bileşenlerinin tanımları zorunlu olarak dolaşık olduğundan, "bu X ve bu yüzden X" diyen kısa alıntılar çıkarmak zordur.
James McNellis

En azından açıkça adlandırılmış değişkenler için böyle bir optimizasyona izin verilmediğini söyleyen burada dikkatiniz için ping atın. Çizgiyi nereye çekeceğimi bilmiyorum.
GManNickG

@GManNickG: Bu çok iyi bir trol ;-). Aslında bu sayfaya işaret ettiğinin farkına varmadan önce o bağlantıya üç tıklama aldığım için ...: -O [Her durumda, yarın sabah ofise gidip güncelleme yaptığımda dil spesifikasyonunu yeniden okuyacağım cevap uygun şekilde.]
James McNellis

Oh bok, üzgünüm !!! Sorum cevaplandı, onun yerine buraya bağlanmak istedim . Bu çok kafa karıştırıcı olmalı.
GManNickG

16

Hayır, my_huge_vectoryakalanmayacak. kullanılan[=] tüm değişkenlerin lambda'da yakalandığı anlamına gelir .


6
Evet. O Not kullanılan olsa teknik bir kelime olduğunu ve gerçekten bir tanımı Kural anlamına kullanılır . Örneğin, düşünün void f() { const int size(10); [] { int x[size]; }; }. Burada sizeyakalanmadı ama sorun değil çünkü ODR anlamında kullanılmıyor. (Visual C ++ 2010, VC10 yayınlandıktan sonra spesifikasyon değiştiği için veya bir hata nedeniyle bu kodu kabul etmez; muhtemelen bu gelecek sürümde düzeltilecektir; g ++ 4.5.1 bunu kabul eder.)
James McNellis

@JamesMcNellis endişelenmeyin, MSVC bugün hala bir yığın kokulu saçmalık. bakınız godbolt.org/z/vHnnCX ( lulz için gcc'ye bakın). Bahsedilen; Değerlendirilen bir ifadede görünen herhangi bir tanımlayıcının ODR tarafından neden kullanılmadığını anlamıyorum. Bu durumun bir constexpr olarak yorumlanabileceğini ve dolayısıyla sadece değerin yararlı olduğunu kastetmediğiniz sürece kesinlikle ODR kullanıldığını düşünüyorum. Derleyicinin constşeylerin potansiyel olarak değişmediğini varsaydığından emin değilim . süper agresif optimizasyon bayrağı OX veya benzeri bir şey olmadığı sürece.
v.oddou
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.