我目前有一个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
答案 0 :(得分:2)
智能指针的向量是个好主意。在你的课堂内足够安全 - 提供自动内存释放。
虽然它不是线程安全的,并且在处理通过简单指针给你的外部存储器方面不安全。
请注意,您当前的实现不会删除析构函数中的pItems内存,因此如果在重构后模仿此类,则不应使用智能指针向量,因为它们将删除其指针引用的内存。
另一方面,你无法保证外面没有人不会为提供给你的Initialize的pItem释放内存。如果你想使用智能指针的向量,你应该为这个功能制定合同,清楚地说明你的类声称这个记忆等等 - 然后你应该重做外面的代码,调用你的类来适应新的合同。 如果你不想改变内存处理,那么简单指针的向量就是你要走的路。然而,这段代码非常简单,没有矢量的真正好处。
请注意,这里的开销是为每个缓冲区创建智能指针类并创建向量类。向量的重新分配可以占用更多内存,而无需您直接控制。
答案 1 :(得分:1)
代码有两个问题:
1)违反零/三/五规则:
要解决此问题,您不需要智能指针。要表示具有可变大小的动态数组,请使用HttpResponseProxy{HTTP/1.1 404 Not Found [Server: Apache-Coyote/1.1, X-ASEN: SEN-1343236, Set-Cookie: JSESSIONID=9DF46011711C2828977E17A945D023E1; Path=/; Secure; HttpOnly, X-Seraph-LoginReason: OK, X-AUSERNAME: xxxx, X-Content-Type-Options: nosniff, Content-Type: text/plain, Transfer-Encoding: chunked, Date: Tue, 27 Sep 2016 11:20:35 GMT] ResponseEntityProxy{[Content-Type: text/plain,Chunked: true]}}
。这允许您放弃std:vector<T*>
,m_pBuffer
和析构函数。
2)获取可能的本地数组的元素地址
在m_uSize
中,您将作为参数传递的数组Initialize
的元素的地址作为函数。因此,队列不占用元素的所有权。似乎队列是一个实用程序类,它根本不应该是可复制的:
pItems
注意:强>
红鲱鱼是本地阵列。 您可以考虑使用智能指针,但这是另一个问题。