1

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.?

9
  • 3
    What prevented you from reading the std::vector documentation? Why have you decided to use memset? What did you try after coming to that conclusion? Commented May 8, 2016 at 13:50
  • @LightnessRacesinOrbit: std::vector will normally call the default constructor for the objects it contains. Because this structure is just built-in types, the elements won't be zero initialized. Commented May 8, 2016 at 13:55
  • @MartinBonner: Yes, I am aware of that. The OP needs to perform some research to find out how to zero out his elements. This question exhibits zero research effort. I am trying to prompt the OP to perform some research. Commented May 8, 2016 at 13:55
  • Why do you think he hasn't? Constructing the vector with copies of a zero initialized object, giving the struct a default constructor, and memset are all plausible approaches - and memset may well be the best. Commented May 8, 2016 at 13:58
  • 3
    @MartinBonner std::vector will value-initialize its elements, not default initialize them. So they will be zero initialized. You can find that out by reading some documentation. Commented May 8, 2016 at 13:59

2 Answers 2

1

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.
Sign up to request clarification or add additional context in comments.

9 Comments

The problem with this is that if you ever change the types, potentially making the struct not POD any more, this'll just silently continue zeroing everything out which could be a critical bug. I found one of those in production once that had caused intermittent crashes for years, costing a customer thousands. Prefer a type-safe solution in C++, especially when teaching.
This is not a great example. The shown initialization results in all of the elements having zero initialized data without the call to memset.
@juanchopanza: Chapter and verse please? Given the definition of the struct, the default construction wont zero initialize it. (Or have I got that wrong?)
As I said in another comment, std::vector value initializes the elements.
@MartinBonner, For a specific reference, [vector.cons] says default-inserted elements. [container.requirements.general] clarifies this to be allocator_traits<A>::construct(m, p). From there, [allocator.traits.members] transforms it into a.construct(p, std::forward<Args>(args)...) (because this is the default allocator), and [allocator.members] says this is ::new((void *)p) U(std::forward<Args>(args)...), which is value-initialization when the args pack is empty. It's a bit roundabout, and can change with the allocator, but should be true in nearly every case.
|
1

Reading the comments, there's code you haven't shown that populated your vector. Now you'd like to reuse the storage instead of creating a new one, and you want to re-initialize it.

The canonical answer for any algorithm for any C++ container is likely found among the standard algorithms. In this case, std::fill. Initialize your structure how you like, and copy that to your vector. Along these lines:

a A = {0};
std::fill(vec.begin(), vec.end(), A);

If you're tempted to say that's not fast enough, check. I think you'll find it's quite efficient. The above code is absolutely safe, and works for any correctly initialized argument to fill. I doubt it can be made faster without making some assumptions about the implementation of a.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.