[英]wondering if I can use stl smart pointers for this
我目前有一個c ++類,如下所示:
template<class T>
class MyQueue {
T** m_pBuffer;
unsigned int m_uSize;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(): m_pBuffer(NULL), m_uSize(0), m_uPendingCount(0), m_uAvailableIdx(0),
m_uPendingndex(0)
{
}
~MyQueue()
{
delete[] m_pBuffer;
}
bool Initialize(T *pItems, unsigned int uSize)
{
m_uSize = uSize;
m_uPendingCount = 0;
m_uAvailableIdx = 0;
m_uPendingndex = 0;
m_pBuffer = new T *[m_uSize];
for (unsigned int i = 0; i < m_uSize; i++)
{
m_pBuffer[i] = &pItems[i];
}
return true;
}
};
所以,我有這個指向數組m_pBuffer
對象的指針,我想知道是否有可能用c ++智能指針替換這種處理方式? 我知道我可以做類似的事情:
std::unique_ptr<T> buffer(new T[size]);
使用智能指針矢量是正確的選擇嗎? 這是推薦且安全的嗎?
[編輯]根據答案和評論,我嘗試制作一個線程安全的緩沖區數組。 這里是。 請評論。
#ifndef __BUFFER_ARRAY_H__
#define __BUFFER_ARRAY_H__
#include <memory>
#include <vector>
#include <mutex>
#include <thread>
#include "macros.h"
template<class T>
class BufferArray
{
public:
class BufferArray()
:num_pending_items(0), pending_index(0), available_index(0)
{}
// This method is not thread-safe.
// Add an item to our buffer list
void add(T * buffer)
{
buffer_array.push_back(std::unique_ptr<T>(buffer));
}
// Returns a naked pointer to an available buffer. Should not be
// deleted by the caller.
T * get_available()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == buffer_array.size()) {
return NULL;
}
T * buffer = buffer_array[available_index].get();
// Update the indexes.
available_index = (available_index + 1) % buffer_array.size();
num_pending_items += 1;
return buffer;
}
T * get_pending()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == 0) {
return NULL;
}
T * buffer = buffer_array[pending_index].get();
pending_index = (pending_index + 1) % buffer_array.size();
num_pending_items -= 1;
}
private:
std::vector<std::unique_ptr<T> > buffer_array;
std::mutex buffer_array_mutex;
unsigned int num_pending_items;
unsigned int pending_index;
unsigned int available_index;
// No copy semantics
BufferArray(const BufferArray &) = delete;
void operator=(const BufferArray &) = delete;
};
#endif
智能指針向量是個好主意。 在您的類中足夠安全-提供自動內存重新分配。
但是它不是線程安全的,並且在處理由簡單指針提供給您的外部內存方面也不安全。
請注意,當前的實現不會刪除析構函數中的pItems內存,因此,如果在重構后模仿此類,則不應使用智能指針的向量,因為它們將刪除其指針引用的內存。
另一方面,您不能保證外面沒有人不會為提供給Initialize的pItem分配內存。 如果要使用智能指針矢量,則應為此函數制定契約,以明確聲明您的類聲明了該內存等。然后,您應該對調用類的外部代碼進行重新處理以適應新的契約。 如果您不想更改內存處理方式,那么簡單指針向量是您的最佳選擇。 然而,這段代碼是如此簡單,以至於vector並沒有真正的好處。
請注意,這里的開銷是為每個緩沖區創建智能指針類以及創建矢量類。 向量的重新分配會占用更多內存,並且在沒有您直接控制的情況下會發生。
該代碼有兩個問題:
1)違反零/三/五規則:
要解決此問題,這里不需要智能指針。 要表示大小可變的動態數組,請使用std:vector<T*>
。 這也允許您刪除m_pBuffer
, m_uSize
和析構函數。
2)獲取可能的本地數組元素的地址
在Initialize
,獲取作為參數傳遞給函數的pItems
數組元素的地址。 因此,隊列不擁有元素的所有權。 隊列似乎是一個實用程序類,它根本不可復制:
template<class T>
class MyQueue
{
std::vector<T*> m_buffer;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(T *pItems, unsigned int uSize)
: m_buffer(uSize, nullptr), m_uPendingCount(0), m_uAvailableIdx(0), m_uPendingndex(0)
{
for (unsigned int i = 0; i < uSize; i++)
{
m_buffer[i] = &pItems[i];
}
}
private:
MyQueue(const MyQueue&); // no copy (C++11 use: = delete)
MyQueue& operator = (const MyQueue&); // no copy (C++11 use: = delete)
};
注意:
紅鯡魚是本地陣列。 您可能為此考慮了一個智能指針,但這是另一個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.