如果需要存储DELERE,唯一的_ptr如何没有开销



首先看一下C 底漆对unique_ptrshared_ptr的说法:
$ 16.1.6。效率和灵活性

我们可以确定 shared_ptr不会将Deleter作为直接成员,,因为直到运行时间才知道deleter的类型。

由于eleter的类型是unique_ptr类型的一部分,因此在编译时已知DELETER成员的类型。 deleter可以直接存储在每个unique_ptr对象中。

因此,shared_ptr似乎没有DELERE的直接成员,但是unique_ptr可以。但是,另一个问题的顶级答案说:

如果将eLeter作为模板参数(如unique_ptr中(提供,则它是类型的一部分,您不需要在此类型的对象中存储任何其他内容。如果将deleter作为构造函数的参数传递(如shared_ptr中(,则需要将其存储在对象中。这是额外灵活性的成本,因为您可以将不同的删除器用于相同类型的对象。

这两个引用的段落完全矛盾,这使我感到困惑。更重要的是,许多人说unique_ptr的开销为零,因为它不需要存储Deleter作为会员。但是,众所周知,unique_ptr具有unique_ptr<obj,del> p(new obj,fcn)的构造函数,这意味着我们可以将deleter传递给它,因此unique_ptr似乎已将Deleter存储为成员。真是一团糟!

std::unique_ptr<T>很可能是零偏头(具有任何SANE标准图形实现(。std::unique_ptr<T, D>,用于任意D,并非一般零交叉。

原因很简单:如果是空的(如std::default_delete实例化(,则可以使用空基本优化来消除eleter的存储。

似乎混淆您的密钥短语是"直接存储 deleter 可以直接存储"。但是,存储std::default_delete类型的删除毫无意义。如果需要,则可以将其创建为std::default_delete{}

通常,无需存储无状态删除器,因为您可以按需创建它们。

angew的答案很好地解释了发生了什么。

对于那些好奇的事物在封面下的外观

template<typename T, typename D, bool Empty = std::is_empty_v<D>>
class unique_ptr
{
    T* ptr;
    D d;
    // ... 
};
template<typename T, typename D>
class unique_ptr<T, D, true> : D
{
    T* ptr;
    // ...
};

专门用于空删除器并利用空基础优化的优势。

简短介绍:

unique_ptr can 介绍一些小开销,但不是因为deleter,而是因为当您从IT迁移时,必须将其设置为null,如果您使用原始指针,则可以离开旧的指针在容易出现的错误状态下,它仍然指向以前指向的位置。显然,智能优化器可以优化,但不能保证。

回到eleter:

其他答案是正确的,但详尽。因此,这是提及EBO或其他复杂术语的简化版本。

如果DELERE为空(没有状态(,则不需要将其保存在unique_ptr中。如果需要,则可以在需要时构造它。您需要知道的只是eleter类型(这是unique_ptr的模板参数之一(。

对于Exaple,请考虑按照代码,而不是根据无状态对象的需求证明简单的创建。

#include <iostream>
#include <string>
#include <string_view>
template<typename Person>
struct Greeter{
    void greet(){
        static_assert(std::is_empty_v<Person>, "Person must be stateless");
        Person p; // Stateless Person instance constructed on demand
        std::cout << "Hello " << p() << std::endl;
    }
    // ... and not kept as a member.
};
struct Bjarne{
    std::string_view operator()(){
        return "Bjarne";
    }
};
int main() {
    Greeter<Bjarne> hello_bjarne;
    hello_bjarne.greet();
}

相关内容

  • 没有找到相关文章

最新更新