Search code examples
c++arraysstructmemset

using memset to initialize vector of structure which contains array


I have following structure

struct a {
     int array[20]
     int array2[45]
}

I have created vector of this structure

vector<a> vec;

I have used this vec. Now i Want to initialize(setting all array values inside object in the vector element) to zero. How can i do it.?


Solution

  • It turns out that this is a much more interesting question than it first appears.

    tl;dr: If you are using a C++03 or later compiler, you don't need to bother.

    You need to understand the difference between value initialization and default initialization. Basically value initialization will set all the elements to zero, and default initialization wil leave them all alone. If any of the default elements of the structure (recursively) have a user defined default constructor, then both value and default initialization will call that.

    Note that value initialization is much better than memset to zero because

    • It will call default constructors
    • It will correctly initialize floating point (to 0.0) and pointers (to NULL). Although memset will probably do that on your implementation, it isn't guaranteed to.

    The normal way to create a vector with n elements is just to call:

    std::vector<a> vec(n);
    

    C++98

    this will call

    std::vector<a>::vector(size_type count, 
                           const T& value = T(),
                           const Allocator& alloc = Allocator());
    

    The value object will be default constructed, and you will need to initialize the elements somehow. The best way to do that, is to provide a properly value initialized value to be copied. So:

    const static a azeroed;  // Because this is static, it will be value initialized
    std::vector<a> vec(20,azeroed);
    

    Technical note: The C++98 standard doesn't contain the term "value initialization", but the initialization of azeroed is identical.

    C++03

    The same vector constructor is called, but from C++03, the value argument is value initialized (so everything in the garden is rosy).

    C++11

    The call is to

    std::vector<a>::vector(size_type count);
    

    which value initializes the elements directly.

    C++14

    The call is to

    std::vector<a>::vector(size_type count, const Allocator& alloc = Allocator());
    

    (basically, they realized they forgot the allocator argument). There is a very subtle difference here, in that the elements are constructed by calls to Allocator::construct, and although the default allocator will value initialize the elements, it is possible to provide a custom version which doesn't (see this answer). If you are doing that, you almost certainly know what you are doing.

    Conclusion

    • Unless you are using a real C++98 compiler, you don't need to call memset
    • Providing an explicitly value initialized value to the vector constructor is safer than calling memset.
    • memset may not properly initialize non-integral built-in values (although it probably will).
    • memset will definitely clobber anything will a proper constructor. This is a huge maintenance hazard. If a maintenance programmer changes the structure so it is no longer POD, the code will still compile - it will just do the wrong thing.
    • There is a lot to be said for just giving the struct a proper default constructor, and then you never have to worry about whether any of the elements are initialized, even if you have a local copy.