我和非常喜欢memcpy的同事一起工作。我正在移植代码,它通常处理简单类型(主要是double),这些代码可以使用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++中的C++。不幸的是,当我使用-Wall (10.2)用g++编译代码时,我得到了警告
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被错误地使用了。选择正确的操作和沉默警告需要使用哪种类型的特征?
发布于 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
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之间的二进制。他们完全一样。
https://stackoverflow.com/questions/66372303
复制相似问题