Do c ++ 11 lambdas nắm bắt các biến họ không sử dụng?


123

Khi tôi sử dụng [=]để chỉ ra rằng tôi muốn tất cả các biến cục bộ bị bắt bởi giá trị trong lambda, điều đó sẽ dẫn đến tất cả các biến cục bộ trong hàm được sao chép hay chỉ tất cả các biến cục bộ được lambda sử dụng ?

Vì vậy, ví dụ, nếu tôi có:

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

My_huge_vector sẽ được sao chép, mặc dù tôi không sử dụng nó trong lambda?

Câu trả lời:


114

Mỗi biến được đặt tên rõ ràng trong danh sách chụp được chụp. Việc chụp mặc định sẽ chỉ chụp các biến có cả (a) không được đặt tên rõ ràng trong danh sách chụp và (b) được sử dụng trong phần thân của biểu thức lambda. Nếu một biến không được đặt tên rõ ràng và bạn không sử dụng biến trong biểu thức lambda, thì biến đó không được ghi lại. Trong ví dụ của bạn, my_huge_vectorkhông được chụp.

Mỗi C ​​++ 11 §5.1.2 [expr.prim.lambda] / 11:

Nếu một biểu thức lambdamặc định bắt giữ liên quan và sử dụng odr câu lệnh ghép của nó hoặc một biến có thời lượng lưu trữ tự động và thực thể sử dụng odr không được nắm bắt một cách rõ ràng, thì thực thể sử dụng odr được cho là bị bắt hoàn toàn. this

Biểu thức lambda của bạn có mặc định chụp liên quan: theo mặc định, bạn nắm bắt các biến theo giá trị bằng cách sử dụng [=].

Nếu và chỉ khi một biến được sử dụng (theo nghĩa Một quy tắc định nghĩa của thuật ngữ "được sử dụng") là một biến được nắm bắt hoàn toàn. Vì bạn hoàn toàn không sử dụng my_huge_vectortrong cơ thể ("tuyên bố ghép") của biểu thức lambda, nên nó không hoàn toàn bị bắt.

Tiếp tục với §5.1.2 / 14

Một thực thể được chụp bằng bản sao nếu

  • nó được chụp ngầm và mặc định chụp=hoặc nếu
  • nó được chụp một cách rõ ràng với một bản chụp không bao gồm một &.

Vì bạn my_huge_vectorkhông hoàn toàn bị bắt và nó không bị bắt một cách rõ ràng, nên nó hoàn toàn không bị bắt, bởi bản sao hoặc bằng cách tham chiếu.


10
Ngươi có một trích dẫn thánh?
GManNickG

Tuy nhiên, tôi sẽ nói rằng toàn bộ §5.1.2 rất quan trọng để hiểu tất cả các chi tiết. Có rất nhiều thuật ngữ kỹ thuật được định nghĩa trong phần đó và bởi vì các định nghĩa về các thành phần khác nhau của biểu thức lambda nhất thiết bị vướng mắc, rất khó để đưa ra các trích dẫn ngắn mà dứt khoát nói rằng "đây là X và đây là lý do X."
James McNellis

Ping cho sự chú ý của bạn ở đây , cho biết tối ưu hóa như vậy là không được phép, ít nhất là cho các biến được đặt tên rõ ràng. Tôi không chắc chắn nơi để vẽ đường.
GManNickG

@GManNickG: Đó là một số trolling tốt mạnh mẽ ;-). Tôi đã mất ba lần nhấp vào liên kết đó trước khi tôi nhận ra rằng nó thực sự đã trỏ đến trang này ...: -O [Trong mọi trường hợp, tôi sẽ đọc lại thông số ngôn ngữ khi tôi vào văn phòng vào sáng mai và cập nhật câu trả lời thích hợp.]
James McNellis

Ôi, xin lỗi !!! Câu hỏi của tôi đã được trả lời, tôi có nghĩa là liên kết ở đây để thay thế. Điều đó hẳn đã rất khó hiểu.
GManNickG

16

Không, my_huge_vectorsẽ không bị bắt. [=]có nghĩa là tất cả các biến được sử dụng được ghi lại trong lambda.


6
Vâng. Lưu ý rằng được sử dụng là một từ kỹ thuật, tuy nhiên, và thực sự có nghĩa là Quy tắc Một định nghĩa được sử dụng . Vì vậy, ví dụ, xem xét void f() { const int size(10); [] { int x[size]; }; }. Ở đây, sizekhông bị bắt nhưng không sao vì nó không được sử dụng theo nghĩa ODR. (Visual C ++ 2010 không chấp nhận mã này, vì thông số kỹ thuật đã thay đổi sau khi VC10 được phát hành hoặc do lỗi, có lẽ điều này sẽ được sửa trong phiên bản sắp tới; g ++ 4.5.1 chấp nhận nó.)
James McNellis

@JamesMcNellis đừng lo lắng, MSVC vẫn là một đống rác rưởi ngày nay. xem godbolt.org/z/vHnnCX (kiểm tra gcc cho lulz). Mà nói; Tôi không hiểu tại sao bất kỳ số nhận dạng nào xuất hiện trong biểu thức được đánh giá sẽ không được sử dụng ODR. Tôi nghĩ rằng trường hợp này chắc chắn được sử dụng ODR trừ khi bạn có nghĩa là nó có thể được đặt xen kẽ như một constexpr do đó chỉ có giá trị là hữu ích? Tôi không chắc trình biên dịch giả định constcông cụ không có khả năng đột biến. trừ khi có thể tối ưu hóa siêu tích cực cờ OX hoặc công cụ.
v.oddou
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.