[英]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.