当前位置:  开发笔记 > 编程语言 > 正文

C++程序员应该避免memset吗?

如何解决《C++程序员应该避免memset吗?》经验,为你挑选了5个好方法。

我听说c ++程序员应该避免使用memset,

class ArrInit {
    //! int a[1024] = { 0 };
    int a[1024];
public:
    ArrInit() {  memset(a, 0, 1024 * sizeof(int)); }
};

所以考虑到上面的代码,如果你不使用memset,怎么能把[1..1024]填充为0?在C++中memset有什么问题?

谢谢.



1> Charles Salv..:

在C++中std::fill或者std::fill_n可能是更好的选择,因为它是通用的,因此可以在对象和POD上操作.但是,memset对原始字节序列进行操作,因此不应该用于初始化非POD.无论如何,如果类型是POD ,优化的实现std::fill可以在内部使用特化来调用memset.


什么是POD的含义?

2> 小智..:

问题不是在内置类型上使用memset(),而是在类(也称为非POD)类型上使用它们.这样做几乎总是会做错事并经常做致命的事情 - 例如,它可能会践踏虚函数表指针.


在任何具有虚函数的类上使用memset可能都很糟糕.
在某些POD类型(如指针和浮点类型)上使用时,`memset`也存在问题.将所有字节设置为0将无法将指针设置为NULL或将浮点类型设置为0.0.
@toto:POD代表"普通旧数据".本质上,它指的是内置类型或结构或内置类型的联合.如果你可以在C中声​​明它,它可能是C++中的POD.

3> UncleBens..:

零初始化应如下所示:

class ArrInit {
    int a[1024];
public:
    ArrInit(): a() { }
};

至于使用memset,有几种方法可以使用法更加健壮(就像所有这些函数一样):避免硬编码数组的大小和类型:

memset(a, 0, sizeof(a));

对于额外的编译时检查,还可以确保a确实是一个数组(这样才有sizeof(a)意义):

template 
size_t array_bytes(const T (&)[N])  //accepts only real arrays
{
    return sizeof(T) * N;
}

ArrInit() { memset(a, 0, array_bytes(a)); }

但对于非字符类型,我想你用它填充的唯一值是0,零初始化应该已经以某种方式可用.


@Pace:不,你会得到一个语法错误.这些大括号是分隔构造函数体的那些大括号.即使使用实际的数组初始化语法:"int a [1024] = {5};" 只会列出您列出的元素,因此在本例中,只有[0]为5,而不是整个数组.

4> AnT..:

这有什么错memset在C++中的大部分是错的同样的事情memset在C. memset填补物理零位模式存储区域,而在病例几乎100%的现实需要,以填补相应类型的逻辑零值的数组.在C语言中,memset只保证为整数类型正确初始化内存(并且它对所有整数类型的有效性,而不仅仅是char类型,是C语言规范中添加的相对较新的保证).不能保证将任何浮点值正确设置为零,不能保证产生正确的空指针.

当然,上述内容可能被视为过于迂腐,因为在给定平台上活跃的附加标准和约定可能(并且肯定会)扩展其适用性memset,但我仍然建议遵循Occam的剃刀原则:不要依赖任何其他标准和惯例,除非你真的必须这样做.C++语言(以及C语言)提供了几种语言级功能,使您可以使用正确类型的正确零值安全地初始化聚合对象.其他答案已经提到了这些功能.



5> jcoder..:

它"糟糕",因为你没有实现你的意图.

您的目的是将数组中的每个值设置为零,并且您编写的内容是将原始内存区域设置为零.是的,这两件事具有相同的效果,但是简单地将代码编写为零以使每个元素更清晰.

而且,它可能没有效率.

class ArrInit
{
public:
    ArrInit();
private:
    int a[1024];
};

ArrInit::ArrInit()
{
    for(int i = 0; i < 1024; ++i) {
        a[i] = 0;
    }
}


int main()
{
    ArrInit a;
}

使用visual c ++ 2008 32位进行编译并启用优化,将循环编译为 -

; Line 12
    xor eax, eax
    mov ecx, 1024               ; 00000400H
    mov edi, edx
    rep stosd

这几乎就是memset可能会编译的内容.但是如果你使用memset,那么编译器就没有空间来执行进一步的优化,而通过编写你的意图,编译器可能会执行进一步的优化,例如注意到每个元素在被使用之前都被设置为其他元素,所以可以优化初始化,如果您使用了memset,它可能无法轻松完成.

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有