用memcpy替代reinterpret_cast转换vector指针的代码是否等价?
我有一段遗留C++代码包含如下语句:
uint16_t* data = reinterpret_cast<uint16_t*>(array_.data()); // #1
其中array_是std::vector类型。我理解这行代码是将vector首个元素的指针存入data,并告知编译器将其视为uint16_t类型指针。出于某些原因,我想用memcpy替代reinterpret_cast,已写出如下替代代码:
uint16_t* data; memcpy(&data, array_.data(), bytes_per_elem); // #2
其中bytes_per_elem是vector元素的字节大小。我对reinterpret_cast和memcpy的使用不太熟悉,想知道#1和#2是否等价?
完全不等价,两者行为天差地别:
代码#1是指针类型转换:
array_.data()返回指向vector首元素的指针(类型为vector元素类型*),reinterpret_cast<uint16_t*>让编译器把这个内存地址的指针当作uint16_t*类型使用。最终data指向array_的内存起始地址,后续可通过data以uint16_t的方式访问array_的内存内容。代码#2的逻辑完全错误:
memcpy会把array_.data()指向的vector首元素的内容,复制到&data(即指针变量data自身占用的内存空间)中。举个例子,如果array_是std::vector<uint32_t>,bytes_per_elem为4,#2会把array_第一个uint32_t的值直接写入data变量,导致data指向一个完全错误的随机地址,后续访问几乎必然触发内存访问错误。
如果确实想用memcpy实现与#1等价的效果(不推荐,reinterpret_cast更直观),正确写法应该是复制指针本身的二进制表示,而非vector元素的内容:
uint16_t* data; // 复制array_.data()指针的二进制值到data变量,大小为指针的字节数 memcpy(&data, &array_.data(), sizeof(data));
不过这种写法本质和reinterpret_cast类似,都属于类型双关,需要注意严格别名规则以及平台指针大小的一致性(比如32位与64位平台指针长度不同)。
内容的提问来源于stack exchange,提问作者LPo

