繁体   English   中英

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

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM