【C++】内存对齐和简单的内存管理

内存管理

自己申请一个内存块,用来存放构造的数据,使用placement new在内存上构造数据。
示例:

//待操作的数据
struct Data 
{
    Data(int _a, char _b, double _c) :a(_a), b(_b), c(_c) {}
    int    a;
    char   b;
    double c;
};

class Block
{
public:
    template<class T, class... Args>
    T* getPtr(Args&&...args)
    {
        //placement new
        T* ptr = new(block + pos) T(std::forward<Args>(args)...);

        int size = sizeof(T);
        cout << "Request block :" << typeid(T).name() << "    size:" << size << "    pos:" << pos << endl;
        pos += size;
        return ptr;
    }

    void print()
    {
        for (int i = 0; i < 5; ++i)
        {
            for (int j = 0; j < 16; ++j)
            {
                printf("%x|", block[i * 10 + j]);
            }
            cout << endl;
        }
    }

    //直接从内存取出对象
    template<class T>
    T* getPtr(int index) {
        int size = sizeof(T);
        char* p = block + size * index;
        return reinterpret_cast<T*>(p);
    }

private:
    int  pos = 0;
    char block[90] = {0};
};

int main() {
    Block block;
    block.print();

    //申请一个Data数据,内存存放在block中
    Data* ptr1 = block.getPtr<Data>(1,'c', 2.25);
    cout << ptr1->a << "  " << ptr1->b << "  " << ptr1->c << endl;
    block.print();

    Data* ptr2 = block.getPtr<Data>(200, 'd', 122.25);
    cout << ptr2->a << "  " << ptr2->b << "  " << ptr2->c << endl;
    block.print();

    Data* ptr3 = block.getPtr<Data>(1);
    cout << ptr2 << "   " << ptr3 << endl;
    cout << ptr3->a << "  " << ptr3->b << "  " << ptr3->c << endl;

    block.print();
    //注意释放需要手动调用析构函数
    getchar();
    return 0;
}

打印如下:
这里写图片描述
可以看到获取index=1的内存块的数据正如我们创建的一致。

内存对齐

//待操作的数据
struct Data 
{
    Data(int _a, char _b, double _c) :a(_a), b(_b), c(_c) {}
    int    a;
    char   b;
    double c;

    friend ostream& operator << (ostream& out, const Data& ths)
    {
        cout << ths.a << "   " << ths.b << "   " << ths.c << endl;
        return out;
    }
};
template<class T, std::size_t N>
class AlignStorage
{
public:

    //创建内存对齐的对象
    template<class ...Args>
    void emplace_back(Args&& ...args)
    {
        if (m_size >= N)
        {
            throw std::bad_alloc{};
        }
        new(data + m_size) T(std::forward<Args>(args)...);
        ++m_size;       
    }

    //访问对象
    const T& operator[](std::size_t pos) const
    {
        return *reinterpret_cast<const T*>(data + pos);
    }

    //删除对象
    ~AlignStorage()
    {
        for (std::size_t pos = 0; pos < m_size; ++pos)
        {
            reinterpret_cast<T*>(data + pos)->~T();    //手动调用析构函数
        }
    }
private:
    std::size_t         m_size = 0;
    //N个T类型对齐的且未初始化的数据
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
};

原理上来说两者方式是一样的。但是使用内存对齐的好处是:

  1. 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。具体原因稍后解释。

猜你喜欢

转载自blog.csdn.net/gx864102252/article/details/80641193
今日推荐