Một số nguồn trên Internets (cụ thể là this one) nói rằng std :: function sử dụng tối ưu hóa đóng cửa nhỏ, ví dụ: nó không phân bổ đống nếu kích thước đóng cửa thấp hơn một số lượng dữ liệu (link ở trên chỉ ra 16 byte cho gcc)g ++: std :: chức năng khởi tạo với kiểu đóng luôn sử dụng phân bổ đống?
Vì vậy, tôi đã đi đào bới g ++ header
Hình như có hay không tối ưu hóa như vậy được áp dụng quyết định bởi khối mã này trong "chức năng" tiêu đề (g ++ 4.6.3)
static void
_M_init_functor(_Any_data& __functor, _Functor&& __f)
{ _M_init_functor(__functor, std::move(__f), _Local_storage()); }
và một số dòng xuống:
static void
_M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
{ new (__functor._M_access()) _Functor(std::move(__f)); }
static void
_M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
{ __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
};
ví dụ như nếu _Local_storage() là true_type, hơn theo vị trí mới được gọi, nếu không - thường xuyên mới
defintion của _Local_storage là folowing:
typedef integral_constant<bool, __stored_locally> _Local_storage;
và __stored_locally:
static const std::size_t _M_max_size = sizeof(_Nocopy_types);
static const std::size_t _M_max_align = __alignof__(_Nocopy_types);
static const bool __stored_locally =
(__is_location_invariant<_Functor>::value
&& sizeof(_Functor) <= _M_max_size
&& __alignof__(_Functor) <= _M_max_align
&& (_M_max_align % __alignof__(_Functor) == 0));
và cuối cùng là: __is_location_invariant:
template<typename _Tp>
struct __is_location_invariant
: integral_constant<bool, (is_pointer<_Tp>::value
|| is_member_pointer<_Tp>::value)>
{ };
So. theo như tôi có thể nói, loại đóng cửa không phải là một con trỏ hay một con trỏ thành viên. Để xác minh rằng tôi thậm chí đã viết một chương trình thử nghiệm nhỏ:
#include <functional>
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << "max stored locally size: " << sizeof(std::_Nocopy_types) << ", align: " << __alignof__(std::_Nocopy_types) << std::endl;
auto lambda = [](){};
typedef decltype(lambda) lambda_t;
std::cout << "lambda size: " << sizeof(lambda_t) << std::endl;
std::cout << "lambda align: " << __alignof__(lambda_t) << std::endl;
std::cout << "stored locally: " << ((std::__is_location_invariant<lambda_t>::value
&& sizeof(lambda_t) <= std::_Function_base::_M_max_size
&& __alignof__(lambda_t) <= std::_Function_base::_M_max_align
&& (std::_Function_base::_M_max_align % __alignof__(lambda_t) == 0)) ? "true" : "false") << std::endl;
}
và đầu ra là:
max stored locally size: 16, align: 8
lambda size: 1
lambda align: 1
stored locally: false
Vì vậy, câu hỏi của tôi là như sau: được intializing std :: chức năng với lambda luôn kết quả với đống phân bổ? hoặc tôi đang thiếu một cái gì đó?
Tôi xác nhận phát hiện của bạn bởi chương trình này: http://ideone.com/kzae6U Bạn có thể kiểm tra trên kêu vang (http: // melpon.org/wandbox/) rằng cùng một chương trình chỉ phân bổ bộ nhớ cho việc chụp rất lớn ... – PiotrNycz