【发布时间】:2021-02-25 16:16:18
【问题描述】:
我与非常喜欢memcpy(太)的同事一起工作。我正在移植通常处理简单类型的代码(主要是doubles),可以使用memcpy 安全地复制它,并将其扩展到非平凡类型。我想编写一个简单的复制函数,它根据所讨论的类型做正确的事情:
#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++ 中内置的type_traits 来确定要使用的实现。不幸的是,当我使用g++ (10.2) 使用-Wall 编译代码时,我收到了警告
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 的使用不正确。我需要使用哪种类型特征来选择正确的操作并使警告静音?
【问题讨论】:
-
我认为您有此错误,因为即使
is_trivially_copy_assignable为假,编译器仍会看到memcpy代码。您是否尝试过改用std::enable_if? -
is_trivially_copyable 告诉你它是否可以被内存复制
-
“一个做正确事情的简单复制函数” - 我称之为
std::copy。标准库实现者通常会非常非常好地优化此类常用算法。 -
@freakish:不。正如 StoryTeller 正确指出的那样,
std::copy确实是默认副本。它适用于所有可复制类型,并且经常进行优化。它甚至可以击败memcpy,因为memcpy也必须支持未对齐的副本。但是double到double是对齐的。
标签: c++ memcpy typetraits