Assignment与mempcy——在这种情况下会更快
Assignment vs mempcy - which will be faster in this case
两者中哪一个更快:?
1.
char* _pos ..;
short value = ..;
*((short*)_pos = va;
2.
char* _pos ..;
short value = ..;
memcpy(_pos, &value, sizeof(short));
与所有"哪个更快?"问题一样,您应该对其进行基准测试,以便自己查看。如果这很重要,那就问问为什么,然后选择你想要的。
无论如何,您的第一个示例在技术上是未定义的行为,因为您违反了严格别名。所以,如果你不得不在没有基准测试的情况下进行选择,那就选择第二个。
要回答实际问题,哪个更快可能取决于pos
的排列。如果它正确对齐,那么1可能会更快。如果不是,那么2可能会更快,这取决于编译器对它的优化方式。(如果硬件不支持错位访问,1甚至可能崩溃。)
但这都是猜测。你真的需要对它进行基准测试才能确定
至少,您应该查看已编译的程序集:
: *(short *)_pos = value;
mov WORD PTR [rcx], dx
与。
: memcpy(_pos, &value, sizeof(short));
mov WORD PTR [rcx], dx
在这种情况下(在MSVC中),它显示了具有默认优化的完全相同的程序集。因此,您可以期望性能相同。
当gcc
处于-O1
或更高的优化级别时,以下两个函数在x86上编译为完全相同的机器代码:
void foo(char *_pos, short value)
{
memcpy(_pos, &value, sizeof(short));
}
void bar(char *_pos, short value)
{
*(short *)_pos = value;
}
编译器可能以相同的方式实现它们
如果它做得很天真,分配会更快
出于任何实际目的,它们都会很快完成,你不需要担心。
还要注意,您可能存在对齐问题s(_pos
可能在2个字节上未对齐,这可能会在某些处理器上崩溃)和类型双关问题(编译器可能会假设_pos
所指向的内容没有更改,因为您使用short *
编写)。
这有关系吗?第一种情况可能会为您节省一些周期(取决于编译器的复杂程度和优化)。但是,它值得在易用性和可维护性方面受到打击吗?
由于过早优化,引入了许多错误。您应该首先确定瓶颈,如果这个任务就是瓶颈,则对每个选项进行基准测试(注意其他人已经提到的对齐和其他问题)。
问题取决于实现。在实践中,对于只复制sizeof(短)字节的操作,如果速度较慢,那么它将是memcpy。对于相当大的数据集,如果要更快,通常会是memcpy。
如前所述,#1调用未定义的行为。
我们可以看到,简单的作业肯定比两者更容易读写,也不容易出错。清晰性和正确性应该放在第一位,即使在性能关键的领域也是如此,原因很简单,优化正确的代码比修复优化的、不正确的代码更容易。如果这真的是一个C++问题,那么对这样的代码(强制转换或memcpy,将类型系统推到x射线和位周围复制)的需求应该非常非常少。
如果您确信不会出现对齐问题,并且您确实发现这是一个瓶颈情况,那么继续执行第一个操作。
如果你不喜欢给memcpy打电话,那么做一些类似的事情:
*pos = static_cast<char>(value & 0xff );
*(pos+1) = static_cast<char>(value >> 8 );
尽管如果要这样做,那么就使用无符号值。
上面的代码确保您也能得到小的endian。(如果您想要big-endian,显然可以颠倒赋值的顺序)。如果数据以某种二进制blob的形式传递,您可能需要一致的endian-ness,我认为这就是您试图创建的。
如果你想创建二进制Blob,你可能希望使用类似谷歌协议缓冲区的东西。还有boost::serialize,它包括二进制序列化。
您可以通过使用并集来避免破坏别名规则和调用函数:
union {
char* c;
short* s;
} _pos;
short value = ...
_pos->s = value;
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 在这种情况下,java对象是否可以调用本机函数
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- 在这种情况下,我真的复制了字节还是复制了字符?
- 为什么在这种情况下,bool 类型的输出等于 0?
- 在这种情况下,如何传递成员函数而不是函数?
- 为什么在这种情况下递增阵列名称有效?
- 在这种情况下我应该使用哪种设计模式
- 为什么在这种情况下我需要 .template
- 在这种情况下,使用 string_view 是否会导致不必要的字符串复制?
- 我是否访问了已释放的内存,或者在这种情况下DrMemory报告不正确?
- 在这种情况下,"typename..."意味着什么?
- 为什么在这种情况下 x = 44?
- 在这种情况下是私有的吗?试图使操作员<<过载
- 在这种情况下,如何防止C++输出/控制台窗体关闭
- 为什么 lambda nullptr 取消引用在这种情况下有效?
- 为什么在这种情况下,前向声明不起作用?
- 为什么在这种情况下不调用我的虚拟函数实现?
- 在这种情况下,为什么模板即时深度超过限制?
- Assignment与mempcy——在这种情况下会更快