2014-05-06 15 views
7

Tôi biết rằng danh sách chụp làm biến sẵn bên trong một hàm cơ thể lambda như vậy:Làm thế nào để nắm bắt danh sách lambdas thực sự làm việc trong C++ 11?

int pos(0); 
std::function<void()> incPos = [&pos](){ ++pos; }; 
incPos(); //pos is now 1 

Nhưng làm thế nào mà săn bắt thực sự làm việc trên mức biên dịch? Các địa chỉ hoặc giá trị đã chụp được lưu trữ ở đâu?

+1

Lambdas cơ bản là [functors] (http://en.wikipedia.org/wiki/Function_object) mà bạn không phải tự viết. –

Trả lời

9

Mỗi biểu thức lambda tạo ra một đối tượng hàm duy nhất (đóng) lưu trữ các biến bị bắt làm thành viên dữ liệu. Ví dụ, biểu thức lambda trong mã của bạn sẽ được chuyển đổi thành một cái gì đó như thế này bởi trình biên dịch:

struct __uniquely_named_lambda 
{ 
    __uniquely_named_lambda(int& pos) 
    : pos(pos) {} 
    int& pos; 

    void operator()() const 
    { ++pos; } 
}; 

Gọi lambda chỉ đơn giản là một lời kêu gọi operator().

Thành viên dữ liệu là tham chiếu kể từ khi bạn bị bắt bằng tham chiếu. Nếu bạn bị bắt bởi giá trị, nó sẽ là một số đơn giản int. Cũng lưu ý rằng được tạo ra operator()const theo mặc định. Đây là lý do tại sao bạn không thể sửa đổi các biến đã chụp trừ khi bạn sử dụng từ khóa mutable.

+0

Lưu ý, tuy nhiên, ở trên là ** không ** chính xác điều gì xảy ra. Không giống như vòng lặp 'for' ma thuật và giống như phần lớn phần còn lại của C++, đó là hành vi được chuẩn hóa, và hành vi đó không được mã hóa trong mã C++. Đặc biệt, lambda "giả" ở trên có một hàm tạo - bản thân lambdas không cần có (chúng có thể thực hiện nó thông qua phép thuật). Ngoài ra, nếu bạn chuyển lambda "giả" ở trên tham chiếu, nó vẫn hợp lệ miễn là dữ liệu được tham chiếu hợp lệ - một lambda thực về mặt kỹ thuật yêu cầu cả dữ liệu ** và ** biến tham chiếu mà nó bắt giữ vẫn hợp lệ. – Yakk

+1

@Yakk: Theo nguyên tắc as-if, các trình biên dịch luôn có quyền tự do triển khai C++ theo bất kỳ cách nào tìm thấy thích hợp miễn là behavior_obableerv_ là giống hệt nhau. Sự tồn tại của các nhà xây dựng không thể quan sát được. – MSalters

+0

@msalters Sử dụng loại khấu trừ rồi tính các lớp học. Một vài trong số chúng khác nhau dựa trên sự tồn tại của hàm tạo. Các ctors unary không rõ ràng có thể được phát hiện (ngay cả khi private) thông qua quá tải hàm (một lần nữa, gõ thông qua loại khấu trừ), nhưng không chắc chắn nếu tôi có thể làm tương tự với cấu trúc rõ ràng hoặc đa arg (thinkimg '{}' với overloads?) - Tôi không thuyết phục nó không thể quan sát được, nhưng không chắc chắn. – Yakk

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