当前位置:  开发笔记 > 编程语言 > 正文

使POD类可移动

如何解决《使POD类可移动》经验,为你挑选了1个好方法。

我有一个POD课程,我想让它可以提高效率.我将所有数据保存在std::array成员对象中,并使我的公共成员变量引用此std::array对象的部分内容.通过这样做,现在我可以通过std::array在移动构造函数中移动实例来移动整个数据(我知道在编写构造函数之后它不再是字面上的POD类.).

这是一个很好的方法吗?它真的会移动数据吗?请参阅下面的代码输出:移动后std::array,我观察到两个对象具有相同的值.看起来它不会移动,但它会复制数据.这里有什么问题?

#include 

class MyPodClass
{
    private:
        typedef double  TYPE_x;
        typedef double  TYPE_y;
        typedef double  TYPE_z;
        typedef int     TYPE_p;
        typedef int     TYPE_r;
        typedef int     TYPE_s;
        typedef char    TYPE_k;
        typedef char    TYPE_l;
        typedef char    TYPE_m;
        typedef float   TYPE_a;
        typedef float   TYPE_b;
        typedef float   TYPE_c;

        enum TypeSizes
        {
            STARTING_POSITION_x = 0,
            STARTING_POSITION_y = STARTING_POSITION_x + sizeof(TYPE_x),
            STARTING_POSITION_z = STARTING_POSITION_y + sizeof(TYPE_y),
            STARTING_POSITION_p = STARTING_POSITION_z + sizeof(TYPE_z),
            STARTING_POSITION_r = STARTING_POSITION_p + sizeof(TYPE_p),
            STARTING_POSITION_s = STARTING_POSITION_r + sizeof(TYPE_r),
            STARTING_POSITION_k = STARTING_POSITION_s + sizeof(TYPE_s),
            STARTING_POSITION_l = STARTING_POSITION_k + sizeof(TYPE_k),
            STARTING_POSITION_m = STARTING_POSITION_l + sizeof(TYPE_l),
            STARTING_POSITION_a = STARTING_POSITION_m + sizeof(TYPE_m),
            STARTING_POSITION_b = STARTING_POSITION_a + sizeof(TYPE_a),
            STARTING_POSITION_c = STARTING_POSITION_b + sizeof(TYPE_b),
            END_POSITION        = STARTING_POSITION_c + sizeof(TYPE_c),
        };

        std::array MovableBulkData;

    public:
        MyPodClass()
            :   //x(*static_cast(&MovableBulkData[STARTING_POSITION_x])),  // ERROR: Invalid type conversion. Why?
                x(*(TYPE_x*)(&MovableBulkData[STARTING_POSITION_x])),
                y(*(TYPE_y*)(&MovableBulkData[STARTING_POSITION_y])),
                z(*(TYPE_z*)(&MovableBulkData[STARTING_POSITION_z])),
                p(*(TYPE_p*)(&MovableBulkData[STARTING_POSITION_p])),
                r(*(TYPE_r*)(&MovableBulkData[STARTING_POSITION_r])),
                s(*(TYPE_s*)(&MovableBulkData[STARTING_POSITION_s])),
                k(*(TYPE_k*)(&MovableBulkData[STARTING_POSITION_k])),
                l(*(TYPE_l*)(&MovableBulkData[STARTING_POSITION_l])),
                m(*(TYPE_m*)(&MovableBulkData[STARTING_POSITION_m])),
                a(*(TYPE_a*)(&MovableBulkData[STARTING_POSITION_a])),
                b(*(TYPE_b*)(&MovableBulkData[STARTING_POSITION_b])),
                c(*(TYPE_c*)(&MovableBulkData[STARTING_POSITION_c]))
        {
        }

        MyPodClass(MyPodClass && RValue)
            :   MovableBulkData(std::move(RValue.MovableBulkData)),
                x(*(TYPE_x*)(&MovableBulkData[STARTING_POSITION_x])),
                y(*(TYPE_y*)(&MovableBulkData[STARTING_POSITION_y])),
                z(*(TYPE_z*)(&MovableBulkData[STARTING_POSITION_z])),
                p(*(TYPE_p*)(&MovableBulkData[STARTING_POSITION_p])),
                r(*(TYPE_r*)(&MovableBulkData[STARTING_POSITION_r])),
                s(*(TYPE_s*)(&MovableBulkData[STARTING_POSITION_s])),
                k(*(TYPE_k*)(&MovableBulkData[STARTING_POSITION_k])),
                l(*(TYPE_l*)(&MovableBulkData[STARTING_POSITION_l])),
                m(*(TYPE_m*)(&MovableBulkData[STARTING_POSITION_m])),
                a(*(TYPE_a*)(&MovableBulkData[STARTING_POSITION_a])),
                b(*(TYPE_b*)(&MovableBulkData[STARTING_POSITION_b])),
                c(*(TYPE_c*)(&MovableBulkData[STARTING_POSITION_c]))
        {
        }

        const MyPodClass & operator=(MyPodClass && RValue)
        {
            MovableBulkData = std::move(RValue.MovableBulkData);
            return *this;
        }

        TYPE_x & x;
        TYPE_y & y;
        TYPE_z & z;
        TYPE_p & p;
        TYPE_r & r;
        TYPE_s & s;
        TYPE_k & k;
        TYPE_l & l;
        TYPE_m & m;
        TYPE_a & a;
        TYPE_b & b;
        TYPE_c & c;
};

int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
    MyPodClass PodObject1, PodObject2;
    PodObject1.y = 3.4;
    PodObject1.s = 4;
    PodObject1.m = 'm';
    PodObject1.a = 2.3f;

    std::cout << "PodObject1.y = " << PodObject1.y << std::endl;
    std::cout << "PodObject1.s = " << PodObject1.s << std::endl;
    std::cout << "PodObject1.m = " << PodObject1.m << std::endl;
    std::cout << "PodObject1.a = " << PodObject1.a << std::endl << std::endl;

    std::cout << "PodObject2.y = " << PodObject2.y << std::endl;
    std::cout << "PodObject2.s = " << PodObject2.s << std::endl;
    std::cout << "PodObject2.m = " << PodObject2.m << std::endl;
    std::cout << "PodObject2.a = " << PodObject2.a << std::endl << std::endl;

    std::cout << "Moving PodObject1 to PodObject2..." << std::endl << std::endl;
    PodObject2 = std::move(PodObject1);

    std::cout << "PodObject1.y = " << PodObject1.y << std::endl;
    std::cout << "PodObject1.s = " << PodObject1.s << std::endl;
    std::cout << "PodObject1.m = " << PodObject1.m << std::endl;
    std::cout << "PodObject1.a = " << PodObject1.a << std::endl << std::endl;

    std::cout << "PodObject2.y = " << PodObject2.y << std::endl;
    std::cout << "PodObject2.s = " << PodObject2.s << std::endl;
    std::cout << "PodObject2.m = " << PodObject2.m << std::endl;
    std::cout << "PodObject2.a = " << PodObject2.a << std::endl << std::endl;

    std::cout << "Modifying PodObject1 and PodObject2..." << std::endl << std::endl;
    PodObject1.s = 5;
    PodObject2.m = 'n';

    std::cout << "PodObject1.y = " << PodObject1.y << std::endl;
    std::cout << "PodObject1.s = " << PodObject1.s << std::endl;
    std::cout << "PodObject1.m = " << PodObject1.m << std::endl;
    std::cout << "PodObject1.a = " << PodObject1.a << std::endl << std::endl;

    std::cout << "PodObject2.y = " << PodObject2.y << std::endl;
    std::cout << "PodObject2.s = " << PodObject2.s << std::endl;
    std::cout << "PodObject2.m = " << PodObject2.m << std::endl;
    std::cout << "PodObject2.a = " << PodObject2.a << std::endl << std::endl;

    std::cout << std::endl;
    _wsystem(L"timeout /t 60 /nobreak");
    return 0;
}

输出:

PodObject1.y = 3.4
PodObject1.s = 4
PodObject1.m = m
PodObject1.a = 2.3

PodObject2.y = -9.25596e+61
PodObject2.s = -858993460
PodObject2.m = ?
PodObject2.a = -1.07374e+08

Moving PodObject1 to PodObject2...

PodObject1.y = 3.4
PodObject1.s = 4
PodObject1.m = m
PodObject1.a = 2.3

PodObject2.y = 3.4
PodObject2.s = 4
PodObject2.m = m
PodObject2.a = 2.3

Modifying PodObject1 and PodObject2...

PodObject1.y = 3.4
PodObject1.s = 5
PodObject1.m = m
PodObject1.a = 2.3

PodObject2.y = 3.4
PodObject2.s = 4
PodObject2.m = n
PodObject2.a = 2.3

John Zwinck.. 6

这是对移动语义的误用.由于您的类包含许多像int和的简单数据成员float,因此实际上无需移动.memcpy()如果你只是以正常,天真的方式写课std::array,没有指针体操,你可能会更好地接受你的编译器给你的东西.

如果你的类包含例如std :: string,那么移动语义在这里会很有用,因为std :: string使用动态分配的内存,可以"移动"(读取:采用)到移动的目标中.

上面当然意味着您可以通过动态分配数组来"修复"您的问题,这将允许您移动它.但最终这将是一种巴洛克式的方式来实现使用一个没有体操的普通POD课程并将其存储在a中的效果std::unique_ptr,这当然能够实现移动语义.



1> John Zwinck..:

这是对移动语义的误用.由于您的类包含许多像int和的简单数据成员float,因此实际上无需移动.memcpy()如果你只是以正常,天真的方式写课std::array,没有指针体操,你可能会更好地接受你的编译器给你的东西.

如果你的类包含例如std :: string,那么移动语义在这里会很有用,因为std :: string使用动态分配的内存,可以"移动"(读取:采用)到移动的目标中.

上面当然意味着您可以通过动态分配数组来"修复"您的问题,这将允许您移动它.但最终这将是一种巴洛克式的方式来实现使用一个没有体操的普通POD课程并将其存储在a中的效果std::unique_ptr,这当然能够实现移动语义.

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有