何时使用移动构造函数/分配 [英] When to use Move Constructors/Assignments

查看:129
本文介绍了何时使用移动构造函数/分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经搜索过,但找不到何时"使用它们的答案.我一直在听到这很好,因为它为我节省了额外的副本.我把它放到我所拥有的每个类中,但是有些类似乎对这没什么意义::S我读了无数关于LValues和RValues的教程,以及std :: move vs. std :: copy vs. memcpy vs. memmove等.甚至还可以在throw()上阅读,但我不确定何时使用它.

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.

我的代码如下:

struct Point
{
    int X, Y;

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

    //All my other operators here..
};

然后我有一个类似(RAII sorta something)的类数组:

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

我应该使用move构造函数和copy构造函数吗?我在Point Class上有它,但是感觉很奇怪,所以我删除了它.然后我在PA课堂上有了它,但我认为它不会做任何事情,所以我也删除了它.然后在我的位图类中,我的编译器抱怨有指针成员但没有重载,所以我这样做了:

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

这是正确的吗?我做错了什么事吗?我需要throw()吗?我的赋值和移动赋值运算符应该真的像那样吗?我需要一份复印作业吗?啊,这么多问题:c我问的最后一个论坛无法回答所有问题,所以我很困惑.最后,我应该对字节使用unique_ptr吗? (这是一个字节/像素的数组.)

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.)

推荐答案

首先,并非所有复制请求都可以被移动代替.仅对右值的复制请求才有资格进行优化.其次,并非所有类型都支持比复制操作更有效的移动操作.一个示例是std :: array.第三,即使支持高效移动操作的类型也可能仅在某些时候支持它们.例子:std :: string.它支持移动,但是在使用SSO(小字符串优化)实现std :: string的情况下,小字符串的移动与复制一样昂贵!

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!

也许,您可以对类型进行相应的分类,然后确定所有需要移动语义的方式.请注意,由于编译器会自动生成移动ctor/assignment运算符,因此存在一些限制,因此建议您记住这些限制.当您明确地指定移动成员时,这会有所帮助.

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.

对于没有明确指定移动成员的类,有一些麻烦之处.还存在显式/隐式删除 移动成员​​的问题,该成员禁止从 rvalues 复制.可在Stroustrup的题为移动或不移动的论文中找到有关隐式生成移动成员的一个非常有价值的问题源. .

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.

关于带有移动语义的异常处理,我建议戴夫·亚伯拉罕(Dave Abraham)的帖子异常移动.

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

我会在有空的时候尝试用一些例子回到这个答案.希望上述链接暂时可以帮助您入门.

这篇关于何时使用移动构造函数/分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆