相关疑难解决方法(0)

为什么对于非TriviallyCopyable的对象,未定义std :: memcpy的行为?

来自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.

c++ memcpy object-lifetime language-lawyer c++11

67
推荐指数
5
解决办法
5355
查看次数

std :: memcpy是否在不同的可复制类型之间是未定义的行为?

我一直在std::memcpy用来规避严格的混叠很长一段时间.

例如,检查a float,像这样:

float f = ...;
uint32_t i;
static_assert(sizeof(f)==sizeof(i));
std::memcpy(&i, &f, sizeof(i));
// use i to extract f's sign, exponent & significand
Run Code Online (Sandbox Code Playgroud)

但是,这次,我检查了标准,我还没有找到任何可以验证这一点的东西.我所发现的是这个:

对于平凡可复制类型T的任何对象(可能重叠的子对象除外),无论对象是否保持类型T的有效值,组成对象的基础字节([intro.memory])都可以复制到char,unsigned char或std :: byte([cstddef.syn])数组.40如果将该数组的内容复制回对象,则该对象应随后保持其原始值.[例如:

#define N sizeof(T)
char buf[N];
T obj;                          // obj initialized to its original value
std::memcpy(buf, &obj, N);      // between these two calls to std?::?memcpy, obj might be modified
std::memcpy(&obj, buf, N);      // at this point, each subobject of obj of scalar …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing undefined-behavior language-lawyer c++17

52
推荐指数
3
解决办法
2898
查看次数