On VC++ 2012, trình biên dịch chọn tự động gọi chuyển đổi cho lambdas stateless (mà không có biến chụp) khi bạn chuyển đổi "lambda stateless thực hiện chức năng con trỏ".
MSDN C++11 Features:
Lambdas
[...] Ngoài ra trong Visual C++ trong Visual Studio 2012, lambdas stateless là chuyển đổi chức năng con trỏ. [...] (Visual C++ trong Visual Studio 2012 thậm chí còn tốt hơn thế, bởi vì chúng tôi đã chuyển đổi lambdas không trạng thái thành con trỏ hàm có quy ước gọi tùy ý. Điều này rất quan trọng khi bạn đang sử dụng API mong đợi những thứ như hàm __stdcall
con trỏ)
EDITED:.
NB: Việc quy đổi gọi là ra khỏi C++ Standard, nó phụ thuộc vào đặc điểm kỹ thuật khác như nền tảng ABI (giao diện nhị phân ứng dụng).
Các câu trả lời sau đây dựa trên mã lắp ráp đầu ra với /FAs compiler option. Vì vậy, nó chỉ là một đoán, và xin vui lòng yêu cầu Microsoft để biết thêm chi tiết; P
Q1. Quy ước gọi hàm lambda C++ là gì?
Q3. Nếu quy ước gọi không được xác định, làm thế nào để tái chế đúng không gian ngăn xếp sau khi đã gọi hàm lambda?
Trước hết, C++ lambda (-expression) KHÔNG phải là một chức năng (hay con trỏ chức năng), bạn có thể gọi operator()
để đối tượng lambda như một chức năng bình thường gọi. Và mã lắp ráp đầu ra nói rằng VC++ 2012 tạo ra lambda-body với chuyển đổi cuộc gọi __thiscall
.
Q2. Làm thế nào để xác định quy ước gọi của hàm lambda C++?
AFAIK, không có cách nào. (Chỉ có thể là __thiscall
)
Q4. Trình biên dịch có tự động tạo nhiều phiên bản của hàm lambda không? ví dụ như các pseudo-code sau: [...]
Có lẽ số VC++ 2012 lambda-type chỉ cung cấp một thực hiện lambda-cơ (void operator()()
), nhưng cung cấp nhiều "chuyển đổi người dùng định nghĩa chức năng con trỏ "cho mỗi chuyển đổi cuộc gọi (con trỏ hàm trả về toán tử với void (__fastcall*)(void)
, void (__stdcall*)(void)
và void (__cdecl*)(void)
loại).
Dưới đây là ví dụ;
// input source code
auto lm = [](){ /*lambda-body*/ };
// reversed C++ code from VC++2012 output assembly code
class lambda_UNIQUE_HASH {
void __thiscall operator()() {
/* lambda-body */
}
// user-defined conversions
typedef void (__fastcall * fp_fastcall_t)();
typedef void (__stdcall * fp_stdcall_t)();
typedef void (__cdecl * fp_cdecl_t)();
operator fp_fastcall_t() { ... }
operator fp_stdcall_t() { ... }
operator fp_cdecl_t() { ... }
};
lambda_UNIQUE_HASH lm;
Liên kết câu hỏi này có vẻ hữu ích: http://stackoverflow.com/questions/14169295/how-to-specify-vc11-lambda-calling-convention – jogojapan
'f1' đang sử dụng' __stdcall' nhưng 'h1' đang sử dụng' __cdecl'; nếu bạn trao đổi những thứ xung quanh nó có hoạt động không? – congusbongus
@Cong, Các lỗi là bình thường và OK là bất thường. – xmllmx