我有很多阵容:
int* arr = new int[BIGNUMBER];
如何快速实现1号码。通常我会做
for(int i = 0; i < BIGNUMBER; i++)
arr[i] = 1
但我认为这需要很长时间。
我可以使用memcpy
或类似的吗?
答案 0 :(得分:13)
您可以尝试使用标准函数std::uninitialized_fill_n
:
#include <memory>
// ...
std::uninitialized_fill_n(arr, BIGNUMBER, 1);
在任何情况下,当涉及到性能时,规则是始终进行测量以支持您的假设 - 特别是如果您要放弃一个清晰,简单的设计来接受更复杂的设计,因为所谓的性能提升
修改强>
请注意 - as Benjamin Lindley mentioned in the comments - 对于琐碎的类型std::uninitialized_fill_n
并没有比更明显的std::fill_n
带来任何优势。对于非平凡类型存在优势,因为std::uninitialized_fill
将允许您分配内存区域,然后在适当位置构造对象。
但是,对于未未初始化的内存区域,不应该陷入调用std::uninitialized_fill_n
的陷阱。例如,以下内容将给出未定义的行为:
my_object* v = new my_object[BIGNUMBER];
std::uninitialized_fill_n(my_object, BIGNUMBER, my_object(42)); // UB!
答案 1 :(得分:4)
动态数组的替代是std::vector<int>
,其构造函数接受每个元素的初始值:
std::vector<int> v(BIGNUMBER, 1); // 'BIGNUMBER' elements, all with value 1.
如前所述,需要衡量绩效。这种方法提供了额外的好处,即内存将自动释放。
答案 2 :(得分:2)
Andy Prowl的std::uninitialized_fill_n()
解决方案的一些可能替代方案,仅供后人使用:
memset
就可以了。memsetw
,但并非随处可见。最后但并非最不重要的是,回应一些评论者:你应该测试一下。编译器往往非常擅长识别和优化这样的模式 - 你可能只是简单地使用简单循环或uninitialized_fill_n
之外的任何东西来处理可移植性或可读性。
您可能对之前的问题感兴趣:
答案 3 :(得分:1)
在启用了优化的Linux / x86 gcc下,您的代码将编译为以下内容:
rax = arr
rdi = BIGNUMBER
400690: c7 04 90 01 00 00 00 movl $0x1,(%rax,%rdx,4)
立即将int(1)
移至rax + rdx
400697: 48 83 c2 01 add $0x1,%rdx
增量寄存器rdx
40069b: 48 39 fa cmp %rdi,%rdx
Cmp rdi to rdx
40069e: 75 f0 jne 400690 <main+0xa0>
如果已达到BIGNUMBER,请跳回去开始。
我的机器上每GB大约需要1秒钟,但我敢打赌的大多数是在物理内存中进行分页以支持未初始化的分配。
答案 4 :(得分:1)
只需将循环展开8或16次即可。像memcpy
这样的函数速度很快,但为方便起见,它们确实存在,而不是比你可能编写的任何东西更快:
for (i = 0; i < BIGNUMBER-8; i += 8){
a[i+0] = 1; // this gets rid of the test against BIGNUMBER, and the increment, on 7 out of 8 items.
a[i+1] = 1; // the compiler should be able to see that a[i] is being calculated repeatedly here
...
a[i+7] = 1;
}
for (; i < BIGNUMBER; i++) a[i] = 1;
编译器可能能够为你展开循环,但为什么要冒这个机会呢?
答案 5 :(得分:-2)
使用memset或memcpy
memset(arr, 0, BIGNUMER);
答案 6 :(得分:-2)
答案 7 :(得分:-2)
memset(arr,1,sizeof(int)* BIGNUMBER);