首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确定类型是否是memcpy-保存?

如何确定类型是否是memcpy-保存?
EN

Stack Overflow用户
提问于 2021-02-25 16:16:18
回答 1查看 168关注 0票数 1

我和非常喜欢memcpy的同事一起工作。我正在移植代码,它通常处理简单类型(主要是double),这些代码可以使用memcpy安全地复制,并将其扩展到不平凡的类型。我想编写一个简单的复制函数,根据所讨论的类型进行正确的操作:

代码语言:javascript
复制
#include <string.h>
#include <vector>
#include <type_traits>

template<class T>
void fancy_copy(const T* src,
                T* dest,
                unsigned int size)
{
  // here:
  if(std::is_trivially_copy_assignable<T>::value)
  {
    memcpy(dest, src, sizeof(T) * size);
  }
  else
  {
    for(unsigned int i = 0; i < size; ++i)
    {
      dest[i] = src[i];
    }
  }
}

class Custom
{
private:
  int value;
public:
  Custom& operator=(const Custom& other)
  {
    value = other.value + 1;
    return *this;
  }
};

int main()
{
  const unsigned int size = 10;

  {
    std::vector<int> source(size, 0);
    std::vector<int> target(size, 0);

    fancy_copy<int>(source.data(), target.data(), size);
  }

  {
    std::vector<Custom> source(size);
    std::vector<Custom> target(size);

    fancy_copy<Custom>(source.data(), target.data(), size);
  }

  return 0;
}

为了确定要使用哪个实现,我使用了内置到C++中的C++。不幸的是,当我使用-Wall (10.2)用g++编译代码时,我得到了警告

代码语言:javascript
复制
warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘class Custom’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]

因此,对于我的Custom类,memcpy被错误地使用了。选择正确的操作和沉默警告需要使用哪种类型的特征?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-25 16:24:02

正确的类型特征是std::is_trivially_copyable,而不是std::is_trivially_copy_assignable

要修复警告,请使用if constexpr而不是if,以便在编译时执行检查,并且只生成两个分支中的一个,作为给定类型T的无条件逻辑。即使由于运行时条件逻辑而无法访问格式错误的调用,编译器也会发出警告,因为生成的代码中仍然存在该调用。

还可以考虑使用来自<algorithm><algorithm>来简化回退的逻辑。

在godbolt.org:演示上试一试。

对于C++11,可以使用std::enable_if选择编译时使用的实现,类似于C++17 if constexpr

代码语言:javascript
复制
template<class T>
typename std::enable_if<std::is_trivially_copyable<T>::value>::type
fancy_copy(const T* src, T* dest, unsigned int size)
{
  memcpy(dest, src, sizeof(T) * size);
}

template<class T>
typename std::enable_if<!std::is_trivially_copyable<T>::value>::type
fancy_copy(const T* src, T* dest, unsigned int size)
{
  std::copy_n(src, size, dest);
}

在godbolt.org:演示上试一试。

但是,正如其他人所指出的,这个fancy_copy最终可能是一个过早的优化,您最好在语义正确的地方使用std::copy_n,允许编译器执行自己的优化。在使用fancy_copy查看自己的std::copy_n时,比较-O3-O3之间的二进制。他们完全一样。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66372303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档