Apakah c ++ 11 lambda menangkap variabel yang tidak mereka gunakan?

124

Ketika saya menggunakan [=]untuk menunjukkan bahwa saya ingin semua variabel lokal ditangkap oleh nilai dalam lambda, apakah itu akan menghasilkan semua variabel lokal dalam fungsi yang disalin, atau hanya semua variabel lokal yang digunakan oleh lambda ?

Jadi, misalnya, jika saya memiliki:

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

Akankah my_huge_vector disalin, meskipun saya tidak menggunakannya di lambda?

Komandan Tinggi4
sumber

Jawaban:

115

Setiap variabel yang secara jelas dinamai dalam daftar tangkapan ditangkap. Tangkapan default hanya akan menangkap variabel yang (a) tidak dinamai secara jelas dalam daftar tangkapan dan (b) digunakan dalam isi ekspresi lambda. Jika sebuah variabel tidak dinamai secara jelas dan Anda tidak menggunakan variabel dalam ekspresi lambda, maka variabel tersebut tidak ditangkap. Dalam contoh Anda, my_huge_vectortidak ditangkap.

Per C ++ 11 §5.1.2 [expr.prim.lambda] / 11:

Jika ekspresi lambda memiliki default capture terkait dan pernyataan majemuk odr-use this atau variabel dengan durasi penyimpanan otomatis dan entitas yang digunakan odr tidak secara eksplisit ditangkap, maka entitas yang digunakan odr dikatakan ditangkap secara implisit.

Ekspresi lambda Anda memiliki default pengambilan terkait: secara default, Anda menangkap variabel dengan nilai menggunakan [=].

Jika dan hanya jika variabel yang digunakan (dalam pengertian Aturan Satu Definisi dari istilah "digunakan") adalah variabel yang ditangkap secara implisit. Karena Anda tidak menggunakan my_huge_vectorsama sekali dalam body ("pernyataan gabungan") ekspresi lambda, ekspresi lambda tidak ditangkap secara implisit.

Untuk melanjutkan dengan §5.1.2 / 14

Entitas ditangkap dengan salinan jika

  • itu secara implisit ditangkap dan capture-defaultnya adalah =atau jika
  • itu secara eksplisit ditangkap dengan tangkapan yang tidak menyertakan file &.

Karena Anda my_huge_vectortidak ditangkap secara implisit dan tidak ditangkap secara eksplisit, maka tidak diambil sama sekali, dengan menyalin atau dengan referensi.

James McNellis
sumber
10
Apakah Anda memiliki Kutipan Suci?
GManNickG
Namun, saya akan mengatakan bahwa keseluruhan §5.1.2 penting untuk memahami semua detailnya. Ada banyak istilah teknis yang didefinisikan di bagian itu dan karena definisi berbagai komponen ekspresi lambda tentu terjerat, sulit untuk mengeluarkan tanda kutip pendek yang secara definitif mengatakan "ini adalah X dan inilah mengapa X."
James McNellis
Ping untuk perhatian Anda di sini , yang mengatakan pengoptimalan seperti itu tidak diizinkan, setidaknya untuk variabel yang disebutkan secara eksplisit. Saya tidak yakin di mana harus menarik garis.
GManNickG
@GManNickG: Itu adalah trolling yang sangat bagus ;-). Saya butuh tiga klik yang bagus dari tautan itu sebelum saya menyadari itu benar-benar mengarah ke halaman ini ...: -O [Bagaimanapun, saya akan membaca ulang spesifikasi bahasa ketika saya masuk ke kantor besok pagi dan memperbarui jawabannya dengan tepat.]
James McNellis
Oh sial, maaf !!! Pertanyaan saya terjawab, saya bermaksud menautkan di sini . Itu pasti sangat membingungkan.
GManNickG
16

Tidak, my_huge_vectortidak akan ditangkap. [=]berarti semua variabel yang digunakan ditangkap di lambda.

Thomas Minor
sumber
6
Ya. Perhatikan bahwa yang digunakan adalah kata teknis, dan sebenarnya berarti Aturan Satu Definisi yang digunakan . Jadi, misalnya, pertimbangkan void f() { const int size(10); [] { int x[size]; }; }. Di sini, sizetidak diambil tapi tidak apa-apa karena tidak digunakan dalam pengertian ODR. (Visual C ++ 2010 tidak menerima kode ini, baik karena spek berubah setelah VC10 dirilis atau karena bug, mungkin ini akan diperbaiki dalam versi yang akan datang; g ++ 4.5.1 menerimanya.)
James McNellis
@JamesMcNellis jangan khawatir, MSVC masih tumpukan sampah yang bau hari ini. cf. godbolt.org/z/vHnnCX (periksa di gcc untuk lulz). Yang mengatakan; Saya tidak mengerti mengapa pengenal apa pun yang muncul dalam ekspresi yang dievaluasi tidak akan digunakan ODR. Saya pikir kasus ini pasti digunakan ODR kecuali yang Anda maksud itu dapat diinterpretasikan sebagai sebuah konsteksp sehingga hanya nilainya yang berguna? Saya tidak yakin kompilator menganggap constbarang tidak berpotensi bermutasi. kecuali mungkin bendera pengoptimalan super agresif OX atau semacamnya.
v.oddou