Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
83 views
in Technique[技术] by (71.8m points)

c++ - When to use Move Constructors/Assignments

I've searched but cannot find the answer to "When" to use them. I just keep hearing that it's good because it saves me that extra copy. I went around putting it in every class I had but some how that didn't seem to make sense for some classes :S I've read countless tutorials on LValues and RValues and std::move vs. std::copy vs. memcpy vs. memmove, etc. And even read up on throw() but I'm not sure on when to use that either.

My code looks like:

struct Point
{
    int X, Y;

    Point();
    Point(int x, int y);
    ~Point();

    //All my other operators here..
};

Then I have a class array of that like(RAII sorta thing):

class PA
{
    private:
        std::vector<Point> PointsList;

    public:
        PA();
        //Variadic Template constructor here..
        ~PA();
        //Operators here..
 };

Should I be using a move constructor and copy constructor? I had it in the Point Class but it felt weird so I removed it. Then I had it in the PA class but I thought that it won't do anything much so I removed it too. Then in my bitmaps class my compiler was complaining about having pointer members but no overload so I did:

//Copy Con:
BMPS::BMPS(const BMPS& Bmp) : Bytes(((Bmp.width * Bmp.height) != 0) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    std::copy(Bmp.Bytes, Bmp.Bytes + (width * height), Bytes);
    BMInfo = Bmp.BMInfo;
    bFHeader = Bmp.bFHeader;
}

//Move Con:
BMPS::BMPS(BMPS&& Bmp) : Bytes(nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    Bmp.Swap(*this);
    Bmp.Bytes = nullptr;
}

//Assignment:
BMPS& BMPS::operator = (BMPS Bmp)
{
    Bmp.Swap(*this);
    return *this;
}

//Not sure if I need Copy Assignment?

//Move Assignment:
BMPS& BMPS::operator = (BMPS&& Bmp)
{
    this->Swap(Bmp);
    return *this;
}

//Swap function (Member vs. Non-member?)
void BMPS::Swap(BMPS& Bmp) //throw()
{
    //I was told I should put using std::swap instead here.. for some ADL thing.
    //But I always learned that using is bad in headers.
    std::swap(Bytes, Bmp.Bytes);
    std::swap(BMInfo, Bmp.BMInfo);
    std::swap(width, Bmp.width);
    std::swap(height, Bmp.height);
    std::swap(size, Bmp.size);
    std::swap(bFHeader, Bmp.bFHeader);
}

Is this correct? Did I do something bad or wrong? Do I need throw()? Should my assignment and move assignment operators actually be the same like that? Do I need a copy assignment? Ahh so many questions :c The last forum I asked on could not answer all so I was left confused. Finally should I use unique_ptr for Bytes? (Which is an array of bytes/pixels.)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are some excellent thought's on Scott Meyer's blog:

First, not all copy requests can be replaced by moves. Only copy requests for rvalues are eligible for the optimization. Second, not all types support move operations that are more efficient than copying operations. An example is a std::array. Third, even types that support efficient move operations may support them only some of the time. Case in point: std::string. It supports moves, but in cases where std::string is implemented using SSO (the small string optimization), small strings are just as expensive to move as to copy!

Perhaps, you can categorize your types accordingly and then decide which all need move semantics. Note, that there are restrictions on the compiler auto-generating move ctors/assignment operators, so you would be well advised to keep those in mind. This helps when you are explicitly specifying move members.

For classes where you do not specify move members explicitly, there are a few spots of bother. There is also the problem of explicitly/implicitly deleted move member which inhibit copying from rvalues. A highly valuable source of issues with implicit generation of move members can be found in Stroustrup's paper titled To Move or Not to Move.

Regarding exception handling with move semantics I'd suggest Dave Abraham's post Exceptionally Moving.

I'll try to come back to this answer with some examples when I get the time. Hopefully, for the time being the above mentioned links will help you get started.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...