c++ - 在没有 malloc 和 free 的情况下存储和回收堆分配的可变大小对象

标签 c++ memory c++11 memory-management malloc

我想在自由存储上存储从 Base 类派生的可变大小的多态对象。

我还想在同一个内存块中存储一个 bool 值,就在为派生对象保留的内存之前。

/* 
    Desired memory layout for storage of one object:

    base address
    v
    |      |                                   |     
    | bool | . . . . . variable size . . . . . |               
    |      |                                   |
           ^                                   ^
           object address                      end address
*/

我尝试的第一件事是创建一个带有 bool 成员和模板传递参数 std::size_t 对齐存储的 struct > 尺寸。

我试过使用 offsetofreinterpret_cast 就像在 one of my previous questions 中一样, 但程序总是崩溃,我无法调试错误。

因此,我尝试使用 std::mallocstd::free,程序按预期运行。 但是,我现在缺少 C++ new/delete 安全性,而且我没有任何对齐方式。

我真的很想找到一种方法来使用 std::aligned_storage 或确保代码可以在任何平台上运行并且符合标准的东西来重新实现下面的代码。

我想在内存中存储实际对象之前的附加 bool

struct Base { virtual ~Base() { } };
struct Der1 : Base { char c[100]; };
struct Der2 : Base { char c[200]; };

template<typename TBase> struct LocalRecycler
{
    // Allocated, but unused pointers, that can be recycled
    std::vector<void*> recyclable;

    // Upon destruction, free all allocated memory
    // No need to call the destructors, as I'm 100% sure recyclable 
    // pointers alredy destroyed their inner object
    ~LocalRecycler() 
    { 
        for(auto p : recyclable) free(p); 
    }

    // I'm omitting variadic template parameters for generic construction,
    // as they are not relevant to the question
    template<typename T> T* create() 
    {
         void* objAddress;

         // If we have some space that is already allocated, use it
         // Otherwise, allocate new space
         if(!recyclable.empty())
         {
             objAddress = recyclable.back();
             recyclable.pop_back();
         }
         else 
         { 
             // Note how I'm not taking into account alignment here
             // That's one reason why I would like to avoid using `std::malloc`
             objAddress = std::malloc(sizeof(bool) + sizeof(T));
         }

         // Construct a `bool` at the beginning of the allocated memory block
         // Construct a `T' after the bool
         new (objAddress + 0)            bool{true};
         new (objAddress + sizeof(bool)) T{};

         return reinterpret_cast<T*>(objAddress + sizeof(bool));
    }

    void recycle(void* mPtr)
    {
        // Destroy the inner object
        TBase* basePtr{reinterpret_cast<TBase*>(mPtr + sizeof(bool))};
        basePtr->TBase::~TBase();

        // The memory block can now be reused
        recyclable.emplace_back(mPtr);
    }
};

上面的代码似乎在我的程序中运行正常。

我要问的是:如何将上述 C 风格代码“转换”为现代 C++11/C++14 代码,同时还要注意对齐?

最佳答案

似乎创建一个像下面这样的类就可以完成这项工作:

template <typename T>
struct ClassWithBool
{
    bool b;
    T t;
};

然后您可以使用 std::allocator 来分配/销毁对象。

关于c++ - 在没有 malloc 和 free 的情况下存储和回收堆分配的可变大小对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24080690/

相关文章:

c++ - 什么时候应该使用智能指针来保存数组?

c++ - 将 freeglut 回调包装在一个类中的最优雅的方式

c++ - 什么是 Visual Studio 项目引用?

c++ - 使用较旧的 C++ 实现在编译时检查一些编译时定义

c - 直接寻址数组内存

c - 函数指针地址与调试器显示的不一致

c++ - 为什么operator delete的签名要带两个参数?

c++ - Boost::Thread/C++11 std::thread,想要在条件下唤醒工作线程

c++ - 创建树节点时 vtable 的 undefined reference

c++ - 从 vector 数组制作平面文件