简体   繁体   中英

In class assign operator with std::unique_ptr,

I am having a problem with the operator= in my BitMap class. I was having some memory leaks so I decided to change from a raw pointer to a std::unique_ptr . When I did that, I noticed that whenever I use my BitMap assignment operator, I get an error:

function "sp::BitMap::BitMap(const sp::BitMap &)" (declared implicitly) cannot be referenced -- it is a deleted function

.h file

#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 file

//-----------------------------------------------------
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
}
//-----------------------------------------------------

You take the parameter of operator= by value, so this requires marged be copied into the argument as written. However, the implicit copy constructor is ill-formed since m_pixelMap cannot be copied.

Instead, consider move-assigning since the local is going to be destroyed anyway:

*this = std::move(marged);

This move-constructs the argument. The implicit move constructor is well-formed (assuming vector2i is movable).


As an alternative approach, consider replacing one or more of the data members with an std::vector<std::byte> . This will make copying, moving, and destruction all automatic.

If bit-packing of the flags is acceptable in your case (it's hard to tell since we don't see m_pixelMap actually used anywhere) then you can use the specialization std::vector<bool> .

After some testing with std::vector<bool> I found out that this solution consumes too much CPU and memory dropping average FPS from 80 to 6. I couldn't also get std::move() to work for my purposes. So I came back to my original solution and handled the memory leaks. Thanks to @cdhowie for pointing out the unique_ptr copy problem I will remember that for the future.

.h file

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 file

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;
}
//-----------------------------------------------------

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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