为了账号安全,请及时绑定邮箱和手机立即绑定

为什么对于不能TriviallyCopyable的对象,std :: memcpy的行为将无法定义?

为什么对于不能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);}从来没有任何问题。我了解滥用std::memcpy非TriviallyCopyable对象并导致下游未定义行为是微不足道的。但是,我的问题是:std::memcpy与非TriviallyCopyable对象一起使用时,为什么自身的行为不确定?为什么标准认为有必要对此加以说明?更新针对此帖子和该帖子的答案,已修改了http://en.cppreference.com/w/cpp/string/byte/memcpy的内容。当前的描述是:如果对象不是TriviallyCopyable(例如标量,数组,与C兼容的结构),则除非程序不依赖于目标对象的析构函数的影响(不是由memcpy)运行,否则行为是不确定的。目标对象(以结束,但未以开头memcpy)是通过其他某种方式(例如,新放置)来启动的。
查看完整描述

3 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

构造一个memcpy基于该类swap中断的类很容易:


struct X {

    int x;

    int* px; // invariant: always points to x

    X() : x(), px(&x) {}

    X(X const& b) : x(b.x), px(&x) {}

    X& operator=(X const& b) { x = b.x; return *this; }

};

memcpy这样的对象破坏了不变性。


GNU C ++ 11 std::string正是使用短字符串来做到这一点。


这类似于标准文件和字符串流的实现方式。最终从中获得流,std::basic_ios其中包含指向的指针std::basic_streambuf。流还包含作为该指针指向的成员(或基类子对象)的特定缓冲区std::basic_ios。


查看完整回答
反对 回复 2019-10-30
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

因为标准是这样说的。

编译器可能会假定非TriviallyCopyable类型仅通过其复制/移动构造函数/赋值运算符进行复制。这可能是出于优化目的(如果某些数据是私有的,则可以将其设置推迟到复制/移动发生之前)。

编译器甚至可以自由地接听您的memcpy电话,使其无所事事,或格式化硬盘。为什么?因为标准是这样说的。而且无所事事肯定比移动位快得多,那么为什么不优化您的程序memcpy来使它同样有效呢?

现在,在实践中,当您只对不需要的类型的位进行四处查找时,可能会发生许多问题。虚拟功能表可能未正确设置。用于检测泄漏的仪器可能未正确安装。身份包括其位置的对象将完全被您的代码弄乱。

真正有趣的部分是,对于编译器可复制的类型,using std::swap; swap(*ePtr1, *ePtr2);应该可以将其编译memcpy为,对于其他类型,则应定义行为。如果编译器可以证明副本只是被复制的位,则可以将其更改为memcpy。而且,如果您可以编写更优化的代码swap,则可以在相关对象的名称空间中执行。


查看完整回答
反对 回复 2019-10-30
  • 3 回答
  • 0 关注
  • 400 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信