我最近開始將許多現有的類遷移到使用智能指針,並且我有幾個關於如何移植一些我認爲可以從使用智能指針中受益的代碼的問題(但我當然可能是錯的)。我有一個UtlMemBuffer緩衝區管理器類,通過它的頭文件顯示如下。使用智能指針來管理緩衝區
本質上,這個類擁有一個由void */length對組成的緩衝區向量。緩衝區管理是通過一個輔助方法實現的(UtlMemBuffer :: append - 其實現也在下面顯示)。
我想讓這個類使用新的智能指針,這樣可以很好地定義所有權,並且可以最小化重新分配。要使用這個類,客戶端代碼通常將自己的原始指針緩衝區/長度傳遞給構造函數,或者可以調用append。最終,當調用析構函數時,它將釋放它自己的副本,以確保在調用者負責其副本時沒有內存泄漏。我認爲,使用std :: shared_ptr可以避免使用這種類型的雙緩衝區所有權(即調用者將負責新建一個std :: shared_ptr並將它傳遞給在UtlMembuffer。
最大的挑戰,因爲我看到它是支持read方法(界面類似於辦法把一個文件的作品),我需要通過原始指針傳回變平的記憶。也許一個更好的設計方法是我回傳一個std :: unique_ptr,我通過展開shared_ptrs的內部集合來創建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;
}
嗯,我仍然需要知道每個緩衝區的長度,所以從void *更改爲char *實際上不會產生太大的差別。 void */len或char */len是必要的,以便關注每個緩衝區的長度。不幸的是,數組或char []數組 - 不像它們的Java對象沒有長度信息。 – johnco3
@ johnco3:沒有人建議從'void *'改爲'char *',建議從'void *'改成'std :: vector',這個_does_知道它自己的長度。 –
ildjarn
也許從頭文件中不清楚,但std :: vector>後面的意圖僅僅是一個附加的單獨緩衝區的列表,它們只是簡單地「push_back」追加代碼。該向量中的每個緩衝區都有一個指針和一個長度字段。把它看作是一個單獨的單獨緩衝區的鏈表。例如,如果用戶調用read方法,唯一需要將這些變成向量。我希望這很清楚爲什麼我需要一個單獨的長度字段 - 它與void vs char完全無關。 –
johnco3