如果使用lambda,std::unique_ptr如何没有大小开销
How std::unique_ptr have no size overhead if using lambda
继续这个问题,
std::unique_ptr如何没有大小开销?
我做了以下代码,结果出乎意料:
#include <memory>
#include <cstdio>
void f(void *p){
free(p);
}
int main(){
auto x1 = [](void *p){ free(p); };
auto x2 = [](void *p){ f(p); };
printf("%zun", sizeof(std::unique_ptr<int> )); // 8, expected
printf("%zun", sizeof(std::unique_ptr<int, decltype(&f)> )); // 16, expected
printf("%zun", sizeof(std::unique_ptr<int, decltype(x1)> )); // 8, unexpected
printf("%zun", sizeof(std::unique_ptr<int, decltype(x2)> )); // 8, unexpected
}
最后两个lambda类型的大小为8,即使它们做的和f()
相同。
这是怎么做的?
无捕获lambda不需要任何子对象;它只是一个具有CCD_ 2过载的类型。因此,它可以是(但不是必须的(空类型。允许(但不要求(unqiue_ptr
优化其"包含"deleter类型的方式,这样,如果deleter类型是空类类型,则它可以使用各种技术来确保此类型不会占用unique_ptr
实例本身的存储空间。
有几种方法可以做到这一点。unique_ptr
可以从类型继承,依靠EBO来优化基类。使用C++20,它可以将其作为成员子对象,依靠[[no_unique_address]]
属性来提供空成员优化。在任何一种情况下,unique_ptr<T>
所需要的唯一实际存储是指向T
的指针。
相比之下,函数指针就是函数指针。它是一个必须具有存储的基本类型,因为它可以指向任何具有该签名的函数。类型本质上包含要作为类型本身的一部分调用的成员函数;函数指针不会。该类型的实例实际上不需要存储来查找其operator()
。
取消lambdas并简化decltype
s,实际上您写了:
int main(){
struct x1_impl {
void operator()(void *p) { free(p); }
};
x1_impl x1;
struct x2_impl {
void operator()(void *p) { f(p); }
};
x2_impl x2;
printf("%zun", sizeof(std::unique_ptr<int>));
printf("%zun", sizeof(std::unique_ptr<int, void (*)(void*)>));
printf("%zun", sizeof(std::unique_ptr<int, x1_impl>));
printf("%zun", sizeof(std::unique_ptr<int, x2_impl>));
}
CCD_ 11需要同时存储CCD_ 12和CCD_。由于x1_impl
和x2_impl
没有数据成员,它们不需要存储,因此最后两个unique_ptr
只能存储一个T*
。注意,decltype(&f)
是void (*)(void*)
,但operator()
0是未命名的空struct
。Lambdas和函数指针实际上并不相似。对于函数指针,要执行的代码只有在运行时才知道,位于指针后面。对于lambda,要执行的代码在编译时是已知的,lambda对象实际上是闭包,即捕获的变量的集合。这里没有这样的变量,所以Lambda不需要存储任何东西。
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- ifstream什么都没读
- 实现无开销push_back的最佳方法是什么
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- 增强精神 X3:错误:在"..."中没有名为"大小"的类型
- 在C++中释放内存期间,迭代器与指针有何不同
- 类型擦除的std::function与虚拟函数调用的开销
- 一组值的零开销下标运算符
- C++ 特征库:引用的性能开销<>
- 多线程比没有线程C++慢
- 在"结构提升::enable_if<提升::is_pod<T>,无效>"中没有名为"type"的类型
- 您可以在没有线程的情况下同时运行多个 ISR 吗?
- 如何读取没有数组或结构的 3 列文件
- C++ "错误:在'类 std::result_of< ... >"中没有名为'type'的类型"
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++对开销较少的容器使用多个过滤器
- 没有线程安全开销的 QSharedPointer