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

Hos*_*ork 8 c++ gcc memcpy gcc-warning

如果您将警告级别提高到-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 CantCopy' 的对象,没有简单的复制赋值 [-Wclass-memaccess]

memcpy(&dest, &src, sizeof(CantCopy));
Run Code Online (Sandbox Code Playgroud)

我所拥有的是旨在构建为 C 或 C++ 的代码。但是 C++ 构建应该能够静态检查 C 程序员何时进行结构的直接分配——何时应该使用函数。因此禁用复制。

但它仍然是 POD,这一切只是删除了操作符。我可以看到此警告旨在帮助解决的情况,但这不是那种情况。

有没有什么简单的方法可以在不需要禁用警告的情况下执行与此等效的操作?

Pau*_*ulR 1

Move_Value(&cantcopy_dest, &cantcopy_src)通过将赋值运算符和复制构造函数设置为默认和私有并将您添加为朋友,您似乎可以更好地实现在指定函数之外的 C++ 中进行赋值和复制的目标。

struct CantCopy;
#ifdef __cplusplus
extern "C" {
#endif
void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src);
#ifdef __cplusplus
} // extern "C"
#endif


struct CantCopy {
    int i;

#ifdef __cplusplus
    CantCopy () = default;
  private:
    CantCopy (const CantCopy &other) = default;
    constexpr CantCopy &operator= (const CantCopy &rhs) = default;

    friend void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src);
#endif
};

struct Other
{
  CantCopy c;
};

void test()
{
    CantCopy c1;
    CantCopy c2;
    // fails: c3{c1};
    // fails: c2 = c1;
    Move_Value(&c1, &c2);
    Other o;
    Other o2;
    // also fails: o = o2;
}

void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src)
{
    // do special stuff
    *cantcopy_dest = *cantcopy_src;
}
Run Code Online (Sandbox Code Playgroud)