【问题标题】:In class assign operator with std::unique_ptr,在带有 std::unique_ptr 的类赋值运算符中,
【发布时间】:2020-07-20 21:55:02
【问题描述】:

我的BitMap 课程中的operator= 有问题。我遇到了一些内存泄漏,所以我决定从原始指针更改为std::unique_ptr。当我这样做时,我注意到每当我使用我的 BitMap赋值运算符,我得到一个错误:

function "sp::BitMap::BitMap(const sp::BitMap &)" (隐式声明)不能被引用——它是一个被删除的函数

.h 文件

#include "color.h"
#include "spmath.h"
#include <memory>

namespace sp
{   
//Bitmap: saves pixel position in the image
class BitMap
{
public:
    BitMap();
    BitMap(const vector2i& pos, const vector2i& size);
    ~BitMap() {  }

    BitMap& operator=(BitMap bm);

    void marge(BitMap& bm);
    void marge(BitMap* bm, int obj_count);
    void calculateNewRect(const BitMap& bm, sp::vector2i* pos, sp::vector2i* size);
    void calculateNewRect(const BitMap* bm, int obj_count, sp::vector2i* pos, sp::vector2i* size);
    void margeToBitMap(BitMap& target, BitMap& bm);

public:
    //bool* m_pixelMap;
    std::unique_ptr<bool[]> m_pixelMap;
    vector2i m_startPos;
    vector2i m_size;
};
//--------------------------
}

.cpp 文件

//-----------------------------------------------------
sp::BitMap& sp::BitMap::operator=(BitMap bm)
{
    //if(this->m_pixelMap != nullptr)
    //    this->clear();                                //Delete last pixel_map
    this->m_startPos = bm.m_startPos;                   //Copy position
    this->m_size = bm.m_size;                           //Copy size
    this->m_pixelMap.reset(bm.m_pixelMap.release());   //Copy ptr to pixel_map
    //bm.m_pixelMap = nullptr;                           //Delete pointer to pixel map
    return *this;
}
//-----------------------------------------------------


//-----------------------------------------------------
void sp::BitMap::marge(BitMap& bm)  //Margeing to one object
{
    //Calcuating new bitmap size
    vector2i new_pos = this->m_startPos;
    vector2i new_sum_size = this->m_size + new_pos;
    calculateNewRect(bm, &new_pos, &new_sum_size);

    vector2i new_size = new_sum_size - new_pos;
    BitMap marged(new_pos, new_size);
    //------------------------------
    //Mergeing
    margeToBitMap(marged, *this);
    margeToBitMap(marged, bm);
    //------------------------------
    *this = marged; //ERROR
}
//-----------------------------------------------------

【问题讨论】:

  • operator=(BitMap) 按值获取参数,这要求它是可复制的,但由于unique_ptr 成员,它是不可复制的。
  • @IgorTandetnik 参数也可以移动构造。
  • 您使用bool*std::unique_ptr&lt;bool[]&gt; 而不是使用std::vector&lt;bool&gt;(或std::vector&lt;uint8_t&gt;,如果您想避免奇怪的std::vector&lt;bool&gt; 专业化)是否有特殊原因?跨度>

标签: c++ pointers smart-pointers


【解决方案1】:

您按值获取operator= 的参数,因此这需要将marged 复制到写入的参数中。但是,隐式复制构造函数格式不正确,因为无法复制 m_pixelMap

相反,考虑移动分配,因为无论如何本地都会被销毁:

*this = std::move(marged);

这个移动构造了参数。隐式移动构造函数格式正确(假设vector2i 是可移动的)。


作为一种替代方法,请考虑将一个或多个数据成员替换为std::vector&lt;std::byte&gt;。这将使复制、移动和销毁全部自动化。

如果在您的情况下可以接受标志的位打包(很难说,因为我们没有看到 m_pixelMap 在任何地方实际使用),那么您可以使用专门化 std::vector&lt;bool&gt;

【讨论】:

  • 可能也值得进行移动分配,BitMap&amp; operator=(BitMap&amp;&amp; bm);
  • @Eljay 当前的赋值运算符实际上适用于这两种情况,只是在这种情况下,它是通过副本调用的(无法制作)。移动构造参数使其移动分配。
【解决方案2】:

在使用std::vector&lt;bool&gt; 进行一些测试后,我发现此解决方案消耗过多的 CPU 和内存,将平均 FPS 从 80 降至 6。我也无法让 std::move() 为我的目的工作。所以我回到了我原来的解决方案并处理了内存泄漏。感谢@cdhowie 指出unique_ptr 复制问题,我会记住这一点。

.h 文件

namespace sp
{   
    //Bitmap: saves pixel position in the image
    class BitMap
    {
    public:
        BitMap();
        BitMap(const vector2i& pos, const vector2i& size);
        ~BitMap();

        BitMap& operator=(BitMap bm);
        void clear();

        void marge(BitMap& bm);
        void marge(BitMap* bm, int obj_count);
        void calculateNewRect(const BitMap& bm, sp::vector2i* pos, sp::vector2i* size);
        void calculateNewRect(const BitMap* bm, int obj_count, sp::vector2i* pos, sp::vector2i* size);
        void margeToBitMap(BitMap& target, BitMap& bm);

    public:
        bool* m_pixelPosMap;
        vector2i m_startPos;
        vector2i m_size;
    };
//--------------------------
}

.cpp 文件

sp::BitMap::BitMap() :
    m_startPos(sp::vector2i(0, 0)) , m_size(sp::vector2i(0, 0)), m_pixelPosMap(nullptr)
{
}
sp::BitMap::BitMap(const vector2i& pos, const vector2i& size) :
    m_startPos(pos), m_size(size)
{
    m_size.x;
    m_size.y;
    int full_size = m_size.x * m_size.y;

    m_pixelPosMap = new bool[full-size];
    memset(m_pixelPosMap, 0, full_size);    //Clear pixelMap
}

sp::BitMap::~BitMap()
{
}
//-----------------------------------------------------


//-----------------------------------------------------
sp::BitMap& sp::BitMap::operator=(BitMap bm)
{
    this->clear();                                  //Delete last pixel_map
    this->m_startPos = bm.m_startPos;                   //Copy position
    this->m_size = bm.m_size;                           //Copy size
    this->m_pixelPosMap = bm.m_pixelPosMap;             //Copy ptr to pixel_map
    bm.m_pixelPosMap = nullptr;                         //Delete pointer to pixel map
    return *this;
}
//-----------------------------------------------------

void sp::BitMap::clear()
{
    if(m_pixelPosMap != nullptr)
        delete[] m_pixelPosMap;
}

//-----------------------------------------------------
void sp::BitMap::marge(BitMap& bm)  //Margeing to one object
{
    //Calcuating new bitmap size
    vector2i new_pos = this->m_startPos;
    vector2i new_sum_size = this->m_size + new_pos;
    calculateNewRect(bm, &new_pos, &new_sum_size);

    vector2i new_size = new_sum_size - new_pos;
    BitMap marged(new_pos, new_size);
    //------------------------------
    //Margeing
    margeToBitMap(marged, *this);
    margeToBitMap(marged, bm);
    //------------------------------
    *this = marged;
}
//-----------------------------------------------------

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2013-02-17
    • 2020-02-16
    • 1970-01-01
    相关资源
    最近更新 更多