C++ 如何确定类型是否为memcpy save?
我与非常喜欢memcpy的同事一起工作。我移植的代码通常处理简单类型(C++ 如何确定类型是否为memcpy save?,c++,memcpy,typetraits,C++,Memcpy,Typetraits,我与非常喜欢memcpy的同事一起工作。我移植的代码通常处理简单类型(doubles),可以使用memcpy安全地复制这些类型,并将其扩展到非普通类型。我想编写一个简单的复制函数,根据所讨论的类型执行正确的操作: #include <string.h> #include <vector> #include <type_traits> template<class T> void fancy_copy(const T* src,
double
s),可以使用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;
}
因此,对于我的
Custom
类,memcpy
被错误地使用。我需要使用哪种类型特征来选择正确的操作并使警告静音?用于此操作的正确类型特征是,而不是std::is \u琐碎地\u复制\u可分配的
要修复警告,请使用而不是if
在编译时执行检查,并仅生成两个分支中的一个作为给定类型T
的无条件逻辑。即使由于运行时条件逻辑而无法访问格式错误的调用,编译器也会发出警告,因为该调用仍然存在于生成的代码中
也可考虑使用< <代码>
对于C++11,您可以使用来选择编译时要使用的实现,类似于C++17if constexpr
:
模板
typename std::enable_if::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
memcpy(目的地、src、尺寸(T)*尺寸);
}
模板
typename std::enable_if::value>::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
标准:副本(src、大小、目的地);
}
请在godbolt.org上试用:
不过,正如其他人所指出的,这种
fancy\u copy
可能是一种过早的优化,您最好在语义正确的地方使用std::copy\n
,允许编译器执行自己的优化。使用-O3
时,比较和之间的二进制文件,以便自己查看。它们完全相同。用于此的正确类型特征是,而不是std::is\u琐碎地\u copy\u assignable
要修复警告,请使用而不是if
在编译时执行检查,并仅生成两个分支中的一个作为给定类型T
的无条件逻辑。即使由于运行时条件逻辑而无法访问格式错误的调用,编译器也会发出警告,因为该调用仍然存在于生成的代码中
也可考虑使用< <代码>
对于C++11,您可以使用来选择编译时要使用的实现,类似于C++17if constexpr
:
模板
typename std::enable_if::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
memcpy(目的地、src、尺寸(T)*尺寸);
}
模板
typename std::enable_if::value>::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
标准:副本(src、大小、目的地);
}
请在godbolt.org上试用:
不过,正如其他人所指出的,这种
fancy\u copy
可能是一种过早的优化,您最好在语义正确的地方使用std::copy\n
,允许编译器执行自己的优化。使用-O3
时,比较和之间的二进制文件,以便自己查看。它们完全相同。。我认为您有这个错误,因为即使是\u微不足道的\u copy\u assignable
是false,编译器仍然会看到memcpy
代码。你试过用它来代替吗?告诉您它是否可以被memcopy“一个简单的复制函数,它做正确的事情”-我称之为std::copy
。标准库实现者通常会非常好地优化这些常用算法。@freakish:No。正如StoryTeller正确指出的那样,std::copy
实际上是默认副本。它适用于所有可复制类型,并且通常经过优化。它甚至可以击败memcpy
,因为memcpy
也必须支持未对齐的副本。但是double
到double
是对齐的。我认为您有这个错误,因为即使是可分配的是false,编译器仍然会看到memcpy
代码。你试过用它来代替吗?告诉您它是否可以被memcopy“一个简单的复制函数,它做正确的事情”-我称之为std::copy
。标准库实现者通常会非常好地优化这些常用算法。@freakish:No。正如StoryTeller正确指出的那样,std::copy
实际上是默认副本。它适用于所有可复制类型,并且通常经过优化。它甚至可以击败memcpy
,因为memcpy
也必须支持未对齐的副本。但是double
到double
是对齐的。我甚至不知道constepr if
。对于C++17之前的版本,有什么方法可以达到同样的效果吗?@hfhc2您使用的是C++11还是14?好吧,恐怕我已经听命于C++11了是的std::copy\u n
非常快,有时比memcpy
更快,当编译器可以计算对齐时,这可能是一个优势。在C++代码中仍然使用MeMCPY只是货物崇拜编程,我甚至不知道<>代码> CONTXPR,如果。对于C++17之前的版本,有什么方法可以达到同样的效果吗?@hfhc2您使用的是C++11还是14?好吧,恐怕我已经听命于C++11了是的std::copy\u n
非常快,有时比memcpy
更快,当编译器可以计算对齐时,这可能是一个优势。在C++代码中仍然使用MeMCPY只是货物崇拜编程。
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]