使用智能指针来管理缓冲区

问题描述 投票:0回答:2

我最近开始将许多现有的类迁移到使用智能指针,并且我有一些关于如何移植一些我认为可以从使用智能指针中受益的代码的问题(但我当然可能是错的)。 我有一个 UtlMemBuffer 缓冲区管理器类,如下所示通过其头文件。

本质上,这个类拥有一个由 void*/length 对组成的缓冲区向量。缓冲区管理是通过辅助方法实现的(UtlMemBuffer::append - 其实现也如下所示)。

我想让这个类使用新的 C++11 智能指针,以便可以很好地定义所有权并最小化重新分配。 要使用此类,客户端代码通常将其自己的原始指针缓冲区/长度传递给构造函数,或者可以调用append。 最终,当调用 UtlMemBuffer 的析构函数时,它会释放自己的副本,确保在调用者负责其副本时不会发生内存泄漏。 我认为,使用 std::shared_ptr 代替传递原始指针,可以消除对这种类型的双缓冲区所有权的需要(即调用者将负责更新 std::shared_ptr 并将其传递给UtlMembuffer

我认为最大的挑战是支持读取方法(该接口类似于文件的工作方式),我需要通过原始指针传回扁平内存。 也许更好的设计方法是我传回一个 std::unique_ptr,它是我通过展平共享指针的内部集合创建的。 我不太确定最好的方法是什么,尽管我必须更改相当多使用该类的当前代码来采用该方法。

调用者是否应该全部传入

std::shared_ptr 指针作为 ex。 我想知道进行这种转换的最佳方法是什么。

我对这个智能指针业务还很陌生,所以任何建议将不胜感激。 谢谢

/** * Smart Buffer class */ class UtlMemBuffer { public: // default constructor UtlMemBuffer( const UtlPath& rBufferPath = UtlPath::ssNull, const void* pBytes = NULL, const size_t& rBufLength = 0); // copy constructor UtlMemBuffer(const UtlMemBuffer& rhs); // move constructor UtlMemBuffer(UtlMemBuffer&& rhs); inline void swap(UtlMemBuffer& rhs) throw() { // enable ADL (not necessary in our case, but good practice) using std::swap; // no need to swap base members - as we are topmost class swap(mBufferPath, rhs.mBufferPath); swap(mBufferLength, rhs.mBufferLength); swap(mBufferBlocks, rhs.mBufferBlocks); } // unified assignment operator UtlMemBuffer& operator=(UtlMemBuffer rhs); // destructor - pure virtual virtual ~UtlMemBuffer(); // add buffer to this one virtual OsStatus append( const void* pBytes, const size_t& rBufLength, size_t& rBufLengthWritten); // comparator bool operator==(const UtlMemBuffer& rhs) const; // comparator bool operator<(const UtlMemBuffer& rhs) const; // determine the size of the buffer size_t size() const; /** * comparable interface * * @returns 0 if equal, negative val if less than & * negative value if greater. */ virtual int compareTo(const UtlMemBuffer& rhs) const; /** copy the bytes into the designated buffer */ OsStatus read (void* pReturnBuffer, const size_t& rMemBufferOffset, const size_t& rReturnBufferLength, size_t& rBytesRead) const; // free existing linked list of blocks void clear(); // path property void setBufferPath(const UtlPath& rBufferPath); UtlPath getBufferPath() const; private: typedef std::vector< std::pair<void*, size_t> > MemBufInfo; // the name of the buffer (sort of file name) UtlPath mBufferPath; // this is updated whenever we append data size_t mBufferLength; // here we have a collection of received appends (effectively blocks) MemBufInfo mBufferBlocks; };

这是管理对缓冲区块向量的访问的辅助方法。 正如您所看到的,它重新分配原始指针并将它们存储在

mBufferBlocks 成员中。

OsStatus UtlMemBuffer::append(const void* pBytes, const size_t& rBufLength, size_t& rBytesWritten) { rBytesWritten = 0; if (pBytes != NULL) { void* block = new char [rBufLength]; memcpy(block, pBytes, rBufLength); mBufferBlocks.push_back(std::make_pair(block, rBufLength)); rBytesWritten = rBufLength; mBufferLength += rBufLength; } return OS_SUCCESS; }
    
c++ c++11 shared-ptr smart-pointers unique-ptr
2个回答
2
投票
如果作者像平常一样简单地使用 char* 来表示内存字节,那么您可以简单地存储向量而不是 void*/len 对。

这就是我在这里可能会做的事情。 假设您不必对该内存空间中的对象进行任何实际破坏,只需转换为 char* 并粘贴到向量中即可。


0
投票
智能指针并不是实现“内存安全”所必需的,即避免新建和删除。评论者建议将 mBufferBlocks 定义为:

std::vectorstd::vector

mBufferBlocks;

然后你可以通过 mBufferBlocks.length() 知道有多少个“缓冲区块”,并使用 mBufferBlocks[i].length() 知道 i 处缓冲区块的大小。然后通过 mBufferBlocks[i].data(); 访问缓冲区的数据

分配或追加()新缓冲区只是:

mBufferBlocks。

然后在类的 dtor() 中自动实现释放内存。

© www.soinside.com 2019 - 2024. All rights reserved.