首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果使用lambda,std::unique_ptr如何没有大小开销?

如果使用lambda,std::unique_ptr如何没有大小开销?
EN

Stack Overflow用户
提问于 2019-11-01 23:27:57
回答 2查看 206关注 0票数 1

跟进这个问题,

How can std::unique_ptr have no size overhead?

我遵循了代码,结果在某种程度上是出乎意料的:

代码语言:javascript
复制
#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("%zu\n", sizeof(std::unique_ptr<int>                 )); //  8, expected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(&f)>   )); // 16, expected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(x1)>   )); //  8, unexpected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(x2)>   )); //  8, unexpected
}

最后两种类型的lambda大小为8,甚至与f()相同。

这是怎么做的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-01 23:41:47

无捕获的lambda不需要任何子对象;它只是一个具有operator()重载的类型。因此,它可以是(但不需要是)空类型。允许(但不需要) unqiue_ptr优化其“包含”删除类型的方式,以便如果删除类型是空类类型,那么它可以使用各种技术来确保该类型不占用unique_ptr实例本身内的存储。

有几种方法可以做到这一点。unique_ptr可以从类型继承,依靠EBO优化基类。使用C++20,它可以使它成为一个子对象,依赖于[[no_unique_address]]属性来提供空成员优化。在这两种情况下,unique_ptr<T>所需要的唯一实际存储就是指向T的指针。

相反,函数指针就是函数指针。它是一个必须有存储的基本类型,因为它可以指向任何具有该签名的函数。类型本质上包含要作为类型本身的一部分调用的成员函数;函数指针不包含。该类型的实例实际上不需要存储来找到它的operator()

票数 1
EN

Stack Overflow用户

发布于 2019-11-01 23:40:15

对于lambdas和简化decltype,您实际上是这样写的:

代码语言:javascript
复制
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("%zu\n", sizeof(std::unique_ptr<int>));
    printf("%zu\n", sizeof(std::unique_ptr<int, void (*)(void*)>));
    printf("%zu\n", sizeof(std::unique_ptr<int, x1_impl>));
    printf("%zu\n", sizeof(std::unique_ptr<int, x2_impl>));
}

unique_ptr<T, Del>需要同时存储T*Del。因为x1_implx2_impl没有数据成员,所以它们不需要存储,所以最后两个unique_ptr可以只存储一个T*。注意,decltype(&f)void (*)(void*),但是decltype(x1)是一个未命名的空struct。Lambda和函数指针实际上没有什么相似之处。对于函数指针,只有在运行时才知道要执行的代码,它位于指针后面。对于lambda,要执行的代码在编译时是已知的,lambda对象实际上是闭包,是捕获变量的集合。在这里,没有这样的变量,因此lambda不需要存储任何内容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58666958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档