相关疑难解决方法(0)

"放置新"有什么用途?

有没有人曾经使用过C++的"贴牌新品"?如果是这样,那该怎么办?在我看来,它只对内存映射硬件有用.

c++ memory-management placement-new new-operator

385
推荐指数
18
解决办法
16万
查看次数

为什么对于非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
查看次数

在禁用复制的 POD 类型的 memcpy 上避免使用 `-Wclass-memaccess`

如果您将警告级别提高到-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 …

c++ gcc memcpy gcc-warning

8
推荐指数
1
解决办法
2855
查看次数