有没有人曾经使用过C++的"贴牌新品"?如果是这样,那该怎么办?在我看来,它只对内存映射硬件有用.
来自http://en.cppreference.com/w/cpp/string/byte/memcpy:
如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为未定义.
在我的工作中,我们使用std::memcpy了很长时间来按比例交换不是TriviallyCopyable的对象:
void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
static const int size = sizeof(Entity);
char swapBuffer[size];
memcpy(swapBuffer, ePtr1, size);
memcpy(ePtr1, ePtr2, size);
memcpy(ePtr2, swapBuffer, size);
}
Run Code Online (Sandbox Code Playgroud)
从来没有任何问题.
我理解滥用std::memcpy非TriviallyCopyable对象并导致下游的未定义行为是微不足道的.但是,我的问题是:
std::memcpy当与非TriviallyCopyable对象一起使用时,为什么它本身的行为是未定义的?为什么标准认为有必要指定?
UPDATE
http://en.cppreference.com/w/cpp/string/byte/memcpy的内容已经过修改,以回应这篇文章和帖子的答案.目前的描述说:
如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为是未定义的,除非程序不依赖于目标对象(不运行
memcpy)的析构函数的效果和生命周期目标对象(已结束,但未开始memcpy)由其他一些方法启动,例如placement-new.
PS
@Cubbi的评论:
@RSahu如果有东西保证UB下游,它会使整个程序不确定.但我同意在这种情况下似乎可以绕过UB并相应地修改cppreference.
如果您将警告级别提高到-Wall,GCC 8(至少g++ (Ubuntu 8.3.0-6ubuntu1~18.10.1) 8.3.0与--std=c++17)会给出-Wclass-memaccess:
#ifdef __cplusplus
#include <type_traits>
#endif
#include <string.h>
struct CantCopy {
int i;
#ifdef __cplusplus
CantCopy () = default;
CantCopy (const CantCopy &other) = delete;
void operator= (const CantCopy &rhs) = delete;
#endif
};
int main(int argc, char *argv[]) {
#ifdef __cplusplus
static_assert(std::is_pod<CantCopy>::value);
#endif
struct CantCopy src;
src.i = 1020;
struct CantCopy dest;
memcpy(&dest, &src, sizeof(struct CantCopy));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
警告说:
警告:'void* memcpy(void*, const void*, size_t)' 写入类型为 'struct …