假设我有一个大小n
的字节序列(在“真实”代码中可能是1..4个元素),为了这个例子,n = 3
:
char source[n] = { 'a', 'b', 'c' }
我的内存范围足以保存此序列的m
个副本:
char * dest = new char[m*n]
(是的,我知道std::vector
,是的,它通常优先于new
你自己的记忆,不,它不是我目前正在处理的代码的选项 - 无论如何问题仍然是一样的。)
现在,我想要使用dest
m
份副本初始化source
。有多种方法可以执行单个值的m
个副本,但显然没有方法可以执行值的序列的m
个副本。当然,我可以使用嵌套循环:
for ( unsigned i1 = 0; i1 < m; ++i1 )
{
for ( unsigned i2 = 0; i2 < n; ++i2 )
{
dest[ i1 * n + i2 ] = source[ i1 ];
}
}
但不知何故,这种方法缺乏通常告诉我,我得到了解决问题的“正确”解决方案的所有技巧。
C ++是否为此提供了更有效的方法?
答案 0 :(得分:2)
这会给你一个正确的感觉吗? (现场直播here)
auto it = dest;
while ((it = std::copy(source, source + n, it))
!= dest + m * n);
答案 1 :(得分:1)
零初始化是最有效的。其中m很大并且特别是访问稀疏,操作系统甚至可能使用软页面错误来执行相同的虚拟零值内存页面的COW,例如,在实际使用时延迟分配请求的内存。
现在,如果你对每家商店和从字节arrary加载,用来自source的相应字节,可以改变NULL位模式的含义。
dest[ i] = c1 ^ source[ i % n]; // store update
c2 = dest[ j] ^ source[ j % n]; // load, if dest[ j] is 0 it was never updated
在现代的Out Of Order CPU中,与内存缓存未命中相比,操作并不昂贵。
这项技术所需要的是以特定于操作系统的方式分配字节文件,以确保它被归零,例如Linux下的mmap
答案 2 :(得分:1)
我会在for循环中使用std::copy
或std::copy_n
:
for( int i = 0; i < m; ++i )
std::copy_n(source, n, dest+n*i );
for( int i = 0; i < m; ++i )
std::copy(source, source+n, dest+n*i );
答案 3 :(得分:0)
如果m
很大,并且您的memcpy
比基于字节的循环更快,那么在进行“扩展二进制填充”时可能是值得的。 (我不知道它叫什么,因为我刚刚做了它)。这个想法是这样的:
n
字节从source
复制到dest
来填充目标数组n
字节从dest
复制到dest+n
2*n
字节从dest
复制到dest+2*n
4*n
字节从dest
复制到dest+4*n
8*n
字节从dest
复制到dest+8*n
直到你填充了目标数组的至少一半。现在,您可以再添加一份dest
。
这实际上可能比天真版本慢,具体取决于缓存等。因此,如果您尝试这样做,则必须运行一些性能测试。