我有一个POD课程,我想让它可以提高效率.我将所有数据保存在std::array
成员对象中,并使我的公共成员变量引用此std::array
对象的部分内容.通过这样做,现在我可以通过std::array
在移动构造函数中移动实例来移动整个数据(我知道在编写构造函数之后它不再是字面上的POD类.).
这是一个很好的方法吗?它真的会移动数据吗?请参阅下面的代码输出:移动后std::array
,我观察到两个对象具有相同的值.看起来它不会移动,但它会复制数据.这里有什么问题?
#includeclass 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
,这当然能够实现移动语义.
这是对移动语义的误用.由于您的类包含许多像int
和的简单数据成员float
,因此实际上无需移动.memcpy()
如果你只是以正常,天真的方式写课std::array
,没有指针体操,你可能会更好地接受你的编译器给你的东西.
如果你的类包含例如std :: string,那么移动语义在这里会很有用,因为std :: string使用动态分配的内存,可以"移动"(读取:采用)到移动的目标中.
上面当然意味着您可以通过动态分配数组来"修复"您的问题,这将允许您移动它.但最终这将是一种巴洛克式的方式来实现使用一个没有体操的普通POD课程并将其存储在a中的效果std::unique_ptr
,这当然能够实现移动语义.