动态分配并将浮点数数组置零

19

在动态分配数组时如何自动将float数组设置为零(0.0)?

这个可以吗?

float* delay_line = new float[filter_len];

//THIS
memset(delay_line, 0.0, filter_len); //can I do this for a float??

//OR THIS
for (int i = 0; i < filter_len; i++)
  delay_line[i] = 0.0;

哪种方法最高效?

谢谢。

7个回答

34

使用 sizeof(float) * filter_len,除非你在一些奇怪的实现中工作,其中 sizeof(float) == sizeof(char)

memset(delay_line, 0, sizeof(float) * filter_len);

编辑:正如Stephan202在评论中所指出的那样,0.0是一种特别简单的浮点值,适用于memset,因为IEEE标准表示为0.0时,所有位都为零。

memset操作的是内存,而不是数字。第二个参数声明为int,被强制转换为unsigned char类型。如果您的C++实现每个浮点数使用4个字节,则以下关系成立:

  • 如果使用0来进行memset浮点数,则该值将为0.0。
  • 如果使用1来进行memset浮点数,则该值将为2.36943e-38。
  • 如果使用42来进行memset浮点数,则该值将为1.51137e-13。
  • 如果使用64来进行memset浮点数,则该值将为3.00392。

所以0是一个特殊情况。

如果这看起来很奇怪,请记住,memset在<cstring>或<string.h>中声明,通常用于创建像“***************”或“------------------”之类的东西。它可以被用来将内存清零,这是一个巧妙的副作用。

正如Milan Babuškov在评论中指出的,有一个函数bzero(非标准且已弃用),目前在Mac和Linux上可用,但不适用于Microsoft。由于该函数专门用于将内存设置为零,因此安全地省略了一些指令。如果您使用它,并且将来版本的编译器省略了它,则可以在本地兼容性补丁中轻松实现bzero,除非将来版本已经重用了那个名称


谢谢,这会把delay_line中的每个值都设置为0.0吗? - miki
6
是的,这将把每个值都设置为0.0:如果符号、指数和尾数都为0,则浮点数表示为0.0。详见:http://en.wikipedia.org/wiki/IEEE_754-1985。 - Stephan202
IEEE 754与C++标准完全无关。C++标准中没有任何规定要求实现必须遵循IEEE 754。 - Milan Babuškov
此外,如果您选择这条路线,bzero 应该比 memset 更快: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown/ - Milan Babuškov
@Milan:同意,bzero更能表达程序员的意图。看一下glibc中bzero.c和memset.c的实现,bzero能够省略一些|=操作,因为它不需要处理有人传递268435521以获取'A'的情况。遗憾的是,bzero不是标准C。 - Thomas L Holaday

15
#include <algorithm>
...
std::fill_n( delay_line, filer_len, 0 )

如果你不能使用向量,这是最安全、最现代化的C++方法。memset可能更快,但它只是用无类型检查的零字节,如果你的数学计算错误,你就会遇到麻烦。 - iain
我同意fill_n是首选方法,即使它稍微慢一些(只有当我看到它时才会相信;)与memset相比,这种方法既类型安全,而且更容易“可扩展/适应”(您也可以使用此方法初始化为例如4.2) - Pieter

15

动态分配数组的元素可以通过在数组大小后跟一对空括号来初始化为元素类型的默认值:

float* delay_line = new float[filter_len]();

2
现代C++的智慧:这不应该被提升为最佳答案吗? - Ariel Malka

11
使用 std::vector 替代:
std::vector<float> delay_line( filter_len );

向量将被初始化为零。


不是最高效的方式,但肯定是最优雅的。 - Dave Van den Eynde
3
从程序员的工作量角度来看,它是最高效的(不需要管理销毁),通常这是需要优化的最重要的事情。 - anon
1
在堆栈上创建数组时,无需管理析构或构造 :-) - Thomas L Holaday
从程序员的角度来看,最有效的方法是让经理将需要零浮点数组的请求标记为“不予修复”。 - Thomas L Holaday
Thomas,你应该在简历中写上:“有避免修复问题的经验”。 - Dave Van den Eynde

3
现在我们来谈谈:更好的方法是使用vector类。
std::vector< float > delay_line( filter_len, 0.0 );

但是看一下Neil的回答:你不需要0.0参数,这是默认的初始化参数值。 - xtofl

3

另一种选择是使用calloc同时分配内存并将其清零:

float *delay_line = (float *)calloc(sizeof(float), filter_len);

这里的优点是,根据你使用的malloc实现,如果已知数组分配来自已经被清零的内存(通常从操作系统分配的页面),则可能避免清零该数组。
请记住,必须使用free()而不是delete[]释放这样的数组。

2

哪种方式最有效

使用memset可能会稍微快一点,但是谁在乎呢?将微小的优化降到这个级别是完全浪费时间的,除非你在编写计算器,甚至可能也不需要。

我认为memset的方式更清晰,但是我认为你最好检查一下memset的手册……如果你的标准库版本将float作为第二个参数传递给memset函数,我会很惊讶的。

PS:表示零的位模式对于整数和浮点数是相同的……这是设计上的,不仅仅是好运气。

祝你好运;-)

干杯。 Keith。


3
批评微观优化是完全浪费时间。如果QS不需要优化,为什么会问哪种方法最有效? - Dave Van den Eynde
1
我更喜欢使用memset,但不确定浮点数零的二进制表示是否与整数零相同。谢谢你澄清了这个问题。 - miki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接