Initializing an object to all zeroes

后端 未结 12 586
离开以前
离开以前 2020-12-03 01:27

Oftentimes data structures\' valid initialization is to set all members to zero. Even when programming in C++, one may need to interface with an external API for which this

相关标签:
12条回答
  • 2020-12-03 02:00

    The only practical difference is that the ={0}; syntax is a bit clearer about saying "initialize this to be empty" (at least it seems clearer to me).

    Purely theoretically, there are a few situations in which memset could fail, but as far as I know, they really are just that: theoretical. OTOH, given that it's inferior from both a theoretical and a practical viewpoint, I have a hard time figuring out why anybody would want to use memset for this task.

    0 讨论(0)
  • 2020-12-03 02:03

    some_struct s = { 0 }; is guaranteed to work; memset relies on implementation details and is best avoided.

    0 讨论(0)
  • 2020-12-03 02:07

    The best method for clearing structures is to set each field individually:

    struct MyStruct
    {
      std::string name;
      int age;
      double checking_account_balance;
      void clear(void)
      {
         name.erase();
         age = 0;
         checking_account_balance = 0.0;
      }
    };
    

    In the above example, a clear method is defined to set all the members to a known state or value. The memset and std::fill methods may not work due to std::string and double types. A more robust program clears each field individually.

    I prefer having a more robust program than spending less time typing.

    0 讨论(0)
  • 2020-12-03 02:09

    Depending on the compiler optimization, there may be some threshold above which memset is faster, but that would usually be well above the normal size of stack based variables. Using memset on a C++ object with a virtual table is of course bad.

    0 讨论(0)
  • 2020-12-03 02:10

    The bzero function is another option.

    #include <strings.h>
    void bzero(void *s, size_t n);
    
    0 讨论(0)
  • 2020-12-03 02:14

    memset is practically never the right way to do it. And yes, there is a practical difference (see below).

    In C++ not everything can be initialized with literal 0 (objects of enum types can't be), which is why in C++ the common idiom is

    some_struct s = {};
    

    while in C the idiom is

    some_struct s = { 0 };
    

    Note, that in C the = { 0 } is what can be called the universal zero initializer. It can be used with objects of virtually any type, since the {}-enclosed initializers are allowed with scalar objects as well

    int x = { 0 }; /* legal in C (and in C++) */
    

    which makes the = { 0 } useful in generic type-independent C code (type-independent macros for example).

    The drawback of = { 0 } initializer in C89/90 and C++ is that it can only be used as a part of declaration. (C99 fixed this problem by introducing compound literals. Similar functionality is coming to C++ as well.) For this reason you might see many programmers use memset in order to zero something out in the middle of C89/90 or C++ the code. Yet, I'd say that the proper way to do is still without memset but rather with something like

    some_struct s;
    ...
    {
      const some_struct ZERO = { 0 };  
      s = ZERO;
    }
    ...
    

    i.e. by introducing a "fictive" block in the middle of the code, even though it might not look too pretty at the first sight. Of course, in C++ there's no need to introduce a block.

    As for the practical difference... You might hear some people say that memset will produce the same results in practice, since in practice the physical all-zero bit pattern is what is used to represent zero values for all types. However, this is generally not true. An immediate example that would demonstrate the difference in a typical C++ implementation is a pointer-to-data-member type

    struct S;
    ...
    
    int S::*p = { 0 };
    assert(p == NULL); // this assertion is guaranteed to hold
    
    memset(&p, 0, sizeof p);
    assert(p == NULL); // this assertion will normally fail
    

    This happens because a typical implementation usually uses the all-one bit pattern (0xFFFF...) to represent the null pointer of this type. The above example demonstrates a real-life practical difference between a zeroing memset and a normal = { 0 } initializer.

    0 讨论(0)
提交回复
热议问题