想知道我是否可以使用stl智能指针

时间:2016-09-27 10:46:49

标签: c++ stl

我目前有一个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

2 个答案:

答案 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

注意:

红鲱鱼是本地阵列。 您可以考虑使用智能指针,但这是另一个问题。