如何优雅创建一个实例 - levelDB

本文介绍了如何在创建数据库时优雅地使用Options对象,通过LevelDB的单例模式实现,重点讲解了alignof获取结构体对齐长度、placementnew的内存预分配以及aligned_storage确保内存对齐的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何优雅创建一个实例

在创建数据库时,需要传入 Options 该对象在构造的时候需要传入一个对比工具,levelDB中数据库不支持并发,因此在进行创建数据库时每个数据库句柄都是创建之后一直到停止使用结束的,那么这个对比工具也是要保证数据库有效的时间内都能正常使用。

这个时候单例模式就体现出作用来了,这里levelDB使用了经典的饿汉式单例创建方式。这个单例创建模式没有什么新颖的地方,最主要的在这个示例对象中有需要学习的地方。

const Comparator *BytewiseComparator() {
        static NoDestructor<BytewiseComparatorImpl> singleton;
        return singleton.get();
    }
  • alignof 去对其长度,准确的来说就是一个结构体中对齐长度,比如下面的结构体:
struct sql {
    uint64_t data;
    int sql_;
    char name[CREATE_SQL_STR_LEN];
    char tea;
};

alignof(sql) 返回的结果就是8,也就是这个结构体需要按照8字节对其,当我们去除uint64_t的时候,再求对齐长度就会变成4,也就是一个结构体中按照最长位的那个类型进行对齐。

  • 使用 new (ptr) T(args) 特性来实现对象的申请,当我们申请一个对象时,如果想要使用自己指定的内存来存储对象,就可以使用new提供的placement方法来事先,使用方法就是new 后面紧跟一个小括号,并在小括号中放入你想存放对象的内存地址。
  • 使用 aligned_storage 来确保定在定义的数据对象占用内存大小,肯定大于需要对外提供内存的大小。

aligned_storage是C++标准库中的一个模板类,定义在<type_traits>头文件中。它提供了一种用于按照指定对齐要求分配内存的机制。

aligned_storage模板类的定义如下:

template <std::size_t Len, std::size_t Align>
struct aligned_storage;

其中,Len表示所需的内存大小,Align表示所需的对齐要求。

aligned_storage模板类在需要手动控制内存对齐的情况下非常有用。它提供了一种安全和便捷的方式来分配按照指定对齐要求的内存块,并可以通过类型别名来使用这个内存块。

需要注意的是,aligned_storage只提供了对齐内存的分配,但不会自动构造和析构对象。如果需要在对齐内存中存储对象,还需要进行适当的构造和析构操作。

最终代码实现效果

// Wraps an instance whose destructor is never called.
//
// This is intended for use with function-level static variables.
template <typename InstanceType>
class NoDestructor {
    public:
    template <typename... ConstructorArgTypes>
    explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
    static_assert(sizeof(instance_storage_) >= sizeof(InstanceType),
                  "instance_storage_ is not large enough to hold the instance");
    static_assert(
        alignof(decltype(instance_storage_)) >= alignof(InstanceType),
        "instance_storage_ does not meet the instance's alignment requirement");
    new (&instance_storage_)
        InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
    }

    ~NoDestructor() = default;

    NoDestructor(const NoDestructor&) = delete;
    NoDestructor& operator=(const NoDestructor&) = delete;

    InstanceType* get() {
        return reinterpret_cast<InstanceType*>(&instance_storage_);
    }

    private:
    // 注意这里只是申请了一块 >= 指定大小的内存,并不会调用对应对象的构造函数,在对象声明周期结束时也不会调用对象的析构函数,都需要用户自己手动调用
    typename std::aligned_storage<sizeof(InstanceType),
                                alignof(InstanceType)>::type instance_storage_;
};

总结

这一个实例的创建使用了三个比较重要的C++知识点,alignof取结构体对齐长度,new(placement new) 来实现预分配内存的new,在结合 aligned_storage 来保证已有对象内存绝对大于等于需要申请对象的内存,然后经过饿汉式单例模式封装,经过以上几个步骤之后,一个能长久陪伴数据库句柄的对比工具便诞生了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Achilles.Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值