JSON学习笔记-混合任意类型的堆栈

本文探讨了解析JSON时遇到的内存管理问题,提出了使用Placement New和混合类型堆栈的解决方案,有效避免了内存碎片并提升了性能。

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

问题提出

我们在解析JSON时,需要多次调用堆栈来解析对象,这时主要产生了两个问题:
1)多次调用需要大量的申请一块类似的内存空间,然后又释放掉,耗费时间。如果当前系统中有大量的内存碎片,并且我们申请的空间很大,甚至有可能失败。
2)压栈对象的类型不一,而在c++中定义的模板类std::stack中,却只能存储一种类型。

对此我们需要一个可以存放任意类型的混合堆栈,并且可以通过重复使用一块我们提前准备好的内存避免问题 1)。

解决办法

  1. placement new(定位放置new)
    它与普通的new不同,一般申请空间语句为:A* p=new A;而placement new则为:A* p=new (ptr)A;(ptr为指定的内存首地址)。
    顾名思义,定位放置即在用户指定的内存位置上构建新的对象,这个构建过程不需要额外分配内存,只需要调用对象的构造函数即可。
    placement new在已分配好的内存上进行对象的构建,速度大大提升;
    同时已分配好的内存可以反复利用,有效的避免了内存碎片问题。
    一般new和delete成对出现,然而placement new其实是相当于在一块已经分配好的内存上通过调用构造函数进行操作,所以结束后需要调用析构函数并释放内存。

  2. 混合类型堆栈
    我们通过定义以下来实现:

class Stack {
    Stack(Allocator* allocator, size_t stackCapacity);
    ~Stack();

    void Clear();
    void ShrinkToFit();
    
    template<typename T> T* Push(size_t count = 1);
    template<typename T> T* Pop(size_t count);
    template<typename T> T* Top();
    template<typename T> T* Bottom();

    Allocator& GetAllocator();
    bool Empty() const;
    size_t GetSize();
    size_t GetCapacity();
};

此时我们可以使用模板成员函数,压入或弹出不同类型的对象。而且为了完全防止拷贝构造函数调用的可能性,这些函数都是返回指针。

同时这也带来的新的问题:不同的数据类型带来的对齐问题。
对此我们可以使用:std::memcpy来解决:

int i = 123;
std::memcpy(s.Push<int>(), &i, sizeof(i));

int j;
std::memcpy(&j, s.Pop<int>(1), sizeof(j));

混合类型堆栈同时也可以当做一个动态缩放的缓冲区来使用,如:从DOM生成JSON的字符串便可以借助它来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想要暴富的小李

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

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

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

打赏作者

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

抵扣说明:

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

余额充值