2013-03-25 32 views
61

Khi tôi viết một lambda với [=], điều đó có nghĩa là tất cả các biến cục bộ của tôi sẽ được sao chép vào các thành viên của cấu trúc được tạo hoặc tôi có thể giả định rằng chỉ những cái đó thực sự được sử dụng trong lambda? Ví dụ:Liệu [=] ngụ ý rằng tất cả các biến cục bộ sẽ được sao chép?

void f() 
{ 
    vector<int> v(10000); 
    const int n = 5; 
    const int DivByNCnt = count_if(istream_iterator<int>(cin), istream_iterator<int>(), 
      [=](int i) 
      { 
      return i % n == 0; 
      }); 
} 

Điều nào sau đây, nếu có, là đúng?

  • cả n và v sẽ được sao chép
  • n sẽ được sao chép, v sẽ không
  • n sẽ được sao chép, v có thể hoặc có thể không được sao chép tùy thuộc vào các thiết lập implmenentation/tối ưu hóa.

Giả sử vì lý do đó mà hàm tạo bản sao của vector có tác dụng phụ.

+12

Không biết gì về ngữ nghĩa của C++ 11, bất cứ điều gì ngoại trừ chỉ 'n' bị bắt sẽ hoàn toàn điên rồ đối với ngữ nghĩa của mọi ngôn ngữ khác với chức năng ẩn danh hạng nhất và đúng đóng cửa. – Gian

Trả lời

63

Không. Nó chỉ có nghĩa là tất cả các biến cục bộ từ phạm vi môi trường xung quanh có sẵn để tra cứu bên trong phần thân của lambda. Chỉ nếu bạn đề cập đến tên của biến cục bộ xung quanh sẽ biến được ghi lại và biến đó sẽ được ghi lại theo giá trị.

Các ký hiệu "chụp bất kỳ thứ gì" viết tắt =& chỉ là cú pháp, về cơ bản, yêu cầu trình biên dịch "tìm ra ý của tôi".


Một tài liệu tham khảo chính thức từ 5.1.2/11-12:

Nếu một lambda-biểu hiện có liên quan đến chụp mặc định và nó hợp chất-tuyên bố ODR-sử dụng [. ..] một biến với thời gian lưu trữ tự động và thực thể được sử dụng odr không được nắm bắt rõ ràng, khi đó pháp nhân được sử dụng odr được cho là bị bắt hoàn toàn [...]

Một thực thể là bị bắt nếu nó được chụp một cách rõ ràng hoặc ngầm.

Lưu ý rằng "chụp mặc định" đề cập đến [=][&]. Để lặp lại, chỉ định capture-default không capture bất cứ thứ gì; chỉ odr-sử dụng một biến nào.

+3

Tôi chắc chắn rằng bạn là chính xác, nhưng bạn có bất kỳ tài liệu tham khảo? –

+0

@AlexChamberlain: Xem 5.1.2/11-12, về "ẩn và rõ ràng chụp". Đó là * bằng cách sử dụng các biến bên trong cơ thể lambda * mà chụp. –

22

Không! (may mắn)

Bạn có thể thiết lập mã của mình để kiểm tra xem trình biên dịch có thực sự thực hiện hay không. Ví dụ: gcc 4.8.0 dường như tuân thủ.


Như những gì Chuẩn.Hãy nhiệm vụ (làm việc lạc hậu):

§5.1.2/14 Một thực thể là bị bắt bằng cách sao chép nếu nó mặc nhiên được chụp và chụp mặc định là = hoặc nếu nó được chụp rõ ràng với ảnh chụp không bao gồm &. Đối với mỗi thực thể được chụp bởi bản sao, một thành viên dữ liệu không có tên chưa được đặt tên được khai báo trong loại đóng.

$ 5.1.2/11 Nếu biểu thức lambda có liên quan đến chụp mặc định và sử dụng tỷ lệ kết hợp (3.2) this hoặc biến có thời lượng lưu trữ tự động và thực thể được sử dụng không được ghi rõ ràng, thì thực thể được sử dụng odr được cho là bị bắt hoàn toàn; các thực thể như vậy sẽ được khai báo trong phạm vi tiếp cận của biểu thức lambda.

§5.1.2/9 Biểu thức lambda có phạm vi bao quanh nhỏ nhất là phạm vi khối (3.3.3) là biểu thức lambda cục bộ; bất kỳ biểu thức lambda nào khác sẽ không có một danh sách chụp trong trình giới thiệu lambda của nó. đạt phạm vi của biểu thức lambda cục bộ là tập hợp các phạm vi bao quanh lên đến và bao gồm hàm bao trong cùng và các tham số của nó. [Lưu ý: Phạm vi tiếp cận này bao gồm bất kỳ biểu thức lambda can thiệp nào. —end note]

+1

MSVC 10.0 không sao chép v, nhưng tôi muốn biết nếu có bảo đảm rằng v sẽ không được sao chép! –

+0

@ArmenTsirunyan: Tôi đã thêm dấu ngoặc kép tương ứng của Chuẩn. Chỉ những thành viên bị bắt buộc phải được "lưu trữ" trong loại đóng cửa theo §5.1.2/14. –

Các vấn đề liên quan