Tôi muốn một số thông tin về cách nghĩ đúng về các bao đóng C ++ 11 và std::function
về cách chúng được triển khai và cách xử lý bộ nhớ.
Mặc dù tôi không tin vào việc tối ưu hóa quá sớm, nhưng tôi có thói quen xem xét cẩn thận tác động hiệu suất của các lựa chọn của mình trong khi viết mã mới. Tôi cũng thực hiện một lượng lớn lập trình thời gian thực, ví dụ như trên bộ vi điều khiển và hệ thống âm thanh, nơi cần tránh các tạm dừng phân bổ / phân bổ bộ nhớ không xác định.
Do đó, tôi muốn hiểu rõ hơn về thời điểm sử dụng hoặc không sử dụng lambdas C ++.
Sự hiểu biết hiện tại của tôi là một lambda không có bao đóng bị bắt giống hệt như một lệnh gọi lại C. Tuy nhiên, khi môi trường được nắm bắt bằng giá trị hoặc bằng tham chiếu, một đối tượng ẩn danh sẽ được tạo trên ngăn xếp. Khi một hàm đóng giá trị phải được trả về từ một hàm, thì một hàm sẽ bao bọc nó std::function
. Điều gì xảy ra với bộ nhớ đóng trong trường hợp này? Nó có được sao chép từ ngăn xếp vào đống không? Nó có được giải phóng bất cứ khi nào std::function
được giải phóng, tức là, nó có được tính tham chiếu như a std::shared_ptr
không?
Tôi tưởng tượng rằng trong một hệ thống thời gian thực, tôi có thể thiết lập một chuỗi các hàm lambda, chuyển B làm đối số tiếp tục cho A, để một đường dẫn xử lý A->B
được tạo. Trong trường hợp này, các đóng A và B sẽ được phân bổ một lần. Mặc dù tôi không chắc liệu những thứ này sẽ được phân bổ trên ngăn xếp hay đống. Tuy nhiên nói chung điều này có vẻ an toàn khi sử dụng trong hệ thống thời gian thực. Mặt khác, nếu B xây dựng một số hàm lambda C, hàm này trả về, thì bộ nhớ cho C sẽ được cấp phát và phân bổ nhiều lần, điều này sẽ không được chấp nhận cho việc sử dụng thời gian thực.
Trong mã giả, một vòng lặp DSP, mà tôi nghĩ là sẽ an toàn trong thời gian thực. Tôi muốn thực hiện xử lý khối A và sau đó là B, nơi A gọi đối số của nó. Cả hai hàm này đều trả về std::function
các đối tượng, vì vậy f
sẽ là một std::function
đối tượng, nơi môi trường của nó được lưu trữ trên heap:
auto f = A(B); // A returns a function which calls B
// Memory for the function returned by A is on the heap?
// Note that A and B may maintain a state
// via mutable value-closure!
for (t=0; t<1000; t++) {
y = f(t)
}
Và một cái mà tôi nghĩ có thể không tốt khi sử dụng trong mã thời gian thực:
for (t=0; t<1000; t++) {
y = A(B)(t);
}
Và một nơi mà tôi nghĩ rằng bộ nhớ ngăn xếp có khả năng được sử dụng để đóng:
freq = 220;
A = 2;
for (t=0; t<1000; t++) {
y = [=](int t){ return sin(t*freq)*A; }
}
Trong trường hợp sau, bao đóng được xây dựng ở mỗi lần lặp lại của vòng lặp, nhưng không giống như ví dụ trước, nó rẻ vì nó giống như một lệnh gọi hàm, không có phân bổ heap nào được thực hiện. Hơn nữa, tôi tự hỏi liệu một trình biên dịch có thể "dỡ bỏ" việc đóng và thực hiện tối ưu hóa nội tuyến hay không.
Điều này có chính xác? Cảm ơn bạn.
operator()
. Không có "nâng" được thực hiện, lambdas không có gì đặc biệt. Chúng chỉ là một tay ngắn cho một đối tượng chức năng cục bộ.