C++ 使POD类可移动
我有一个POD类,我想让它可以移动以提高效率。我将所有数据保存在C++ 使POD类可移动,c++,move-semantics,C++,Move Semantics,我有一个POD类,我想让它可以移动以提高效率。我将所有数据保存在std::array成员对象中,并将我的公共成员变量引用到此std::array对象的部分。通过这样做,现在我可以通过移动move构造函数中的std::array实例来移动整个数据(我知道在编写构造函数之后,它不再是一个POD类) 这是一种很好的方法吗?它真的移动了数据吗?请参见下面的代码输出:移动std::array后,我发现两个对象的值相同。它看起来没有移动,但它复制了数据。这里有什么问题 #include <array&
std::array
成员对象中,并将我的公共成员变量引用到此std::array
对象的部分。通过这样做,现在我可以通过移动move构造函数中的std::array
实例来移动整个数据(我知道在编写构造函数之后,它不再是一个POD类)
这是一种很好的方法吗?它真的移动了数据吗?请参见下面的代码输出:移动std::array
后,我发现两个对象的值相同。它看起来没有移动,但它复制了数据。这里有什么问题
#include <array>
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<unsigned char, END_POSITION> MovableBulkData;
public:
MyPodClass()
: //x(*static_cast<TYPE_x*>(&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;
}
这是对移动语义的误用。由于您的类包含许多简单的数据成员,如
int
和float
,因此实际上没有什么可以移动的。您最好使用memcpy()
,如果您只是以正常、朴素的方式编写类,没有std::array
和指针练习,这可能接近编译器免费提供的功能
如果您的类包含例如std::string,则移动语义在这里会很有用,因为std::string使用动态分配的内存,这些内存可以“移动”(读取:采用)到移动的目标中
当然,上述情况意味着您可以通过动态分配阵列来“修复”您的问题,这将允许您移动阵列。但最终,这将是一种巴洛克式的方法,可以实现使用不带体操的普通POD类并将其存储在
std::unique_ptr
中的效果,这当然支持移动语义。所有这些值都直接存储在对象本身中。当对象包含指向其他位置分配内存的指针时,移动非常有用,这些内存可能会被盗。这里的情况并非如此。这基本上就是std::array
和std::vector
之间的区别。我怀疑:x(*(TYPE_x*)(&MovableBulkData[start_POSITION_x])
将比仅仅复制值更快或更好。您的缓冲区可能存在对齐问题……吊舱已经可以移动了。立即停止这种胡说八道。POD类是您编写的最有效的数据结构。
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