quick question on STL / vector container

Started by
9 comments, last by ToohrVyk 17 years, 1 month ago
I'm extremely inexperienced with the c++ stl and have a quick question. If you have any help, would be appreciated. I want to use a vector container to have say 10 entries each one being a struct
 vector<struct whatnots> objects; 
objects.resize(10); 
After defining the objects vector, I want to clear all the fields in all of the entries. I know you can iterate through the vector and set each member of each instance of the struct to zero or whatever initial value is appropriate, like such:
 for(i = 0; i < 10; i++){ objects.xxxxx = 0; objects.yyyy = 0; } 
But.... I'm lazy and I want to use memset(). :) when i run the following line of code, the compiler spits out a pretty long warning and I haven't ran the line yet so I can't verify if it's doing what I think it is or not.
 for(i = 0; i < 10; i++) { memset((void*)&objects, 0, sizeof(object struct); } 
is that an appropriate way to clear all the member variables in each instance of the struct? Is it doing something I'm completely missing here? And what's the correct way to do it?
Advertisement
I'd memset a local variable for your struct, and then just loop through and assign it.

whatnots tmp;
memset(&tmp, 0, sizeof(tmp));
for(i = 0; i < 10; i++) objects = tmp;
You could also just write a constructor for the struct that initializes the variables. vector will then call that constructor when inserting the elements.
  std::vector<whatnots> objects(10);  std::memset(&objects[0], 0, object.size() * sizeof(whatnots));


Just be really really sure your whatnots class is truly POD.

--smw

Stephen M. Webb
Professional Free Software Developer

Awesome, thank ya. That works good.

I do love that memset. Especially with the occasional NULL pointer. :D
Quote:Original post by Perost
You could also just write a constructor for the struct that initializes the variables. vector will then call that constructor when inserting the elements.
Agreed. Since you're using C++, you should set the initial state of your struct via a constructor rather than memset().

A couple of other points:

1. In C++ it's not necessary to use the struct keyword when a type is referenced, only when it's declared, e.g.:
struct my_struct {};std::vector<my_struct> v;
2. Classes and structs are identical in C++ apart from default privileges, so don't feel you need to use one or the other for technical reasons. (It's conventional to use structs for simple aggregates with public data, but they can still have constructors and so forth).

3. If your struct really is a POD, then you can initialize it with the {...} syntax as you can with arrays; this should probably be preferred to clearing the struct with memset() when using C++. (Note that the {...} syntax can only be used to initialize the struct, not assign values to it.)

All things considered, initializing via constructor is probably the safest and most convenient option, and obviates the need for setting the state of the object manually after its creation. A quick example:
struct my_struct {    int x, y;    my_struct(int x = 0, int y = 0) : x(0), y(0) {}};std::vector<my_struct> v(10); // Elements initialized to (0,0) automatically// Do some stuff that modifies the elements...// Reset all elements to (0,0) in one go:std::fill(v.begin(), v.end(), my_struct());// Set all elements to (4,2) in one go:std::fill(v.begin(), v.end(), my_struct(4,2));
I agree with those above; you shouldn't be using memset.

However since you love memset so much then the place to use it is inside of the struct's constructor. Thus you keep the initialization logic within the class where it belongs. If you later determine that memset does not work for your type then you just change the constructor instead of all of the places you would have used it.
Quote:Original post by jyk
Quote:Original post by Perost
You could also just write a constructor for the struct that initializes the variables. vector will then call that constructor when inserting the elements.
Agreed. Since you're using C++, you should set the initial state of your struct via a constructor rather than memset().


Even if you think you have a valid use for memset() (in general), in C++ there are no real disadvantages (unless your compiler is out of date) and several real advantages to using std::fill instead. It's both typesafe (i.e. you don't have to worry about the sizeof() your struct) and iterator-safe (i.e. you don't have to extract a pointer to the vector storage, and in fact you can later change the container to, say, a std::list and not have to change your std::fill statement at all, whereas with memset() you'd be, well, screwed).

Quote:
3. If your struct really is a POD, then you can initialize it with the {...} syntax as you can with arrays; this should probably be preferred to clearing the struct with memset() when using C++. (Note that the {...} syntax can only be used to initialize the struct, not assign values to it.)


That doesn't help if you're putting things in a container, though :)

Quote:All things considered, initializing via constructor is probably the safest and most convenient option, and obviates the need for setting the state of the object manually after its creation. A quick example:

struct my_struct {    int x, y;    my_struct(int x = 0, int y = 0) : x(0), y(0) {}};std::vector<my_struct> v(10); // Elements initialized to (0,0) automatically// Do some stuff that modifies the elements...// Reset all elements to (0,0) in one go:std::fill(v.begin(), v.end(), my_struct());// Set all elements to (4,2) in one go:std::fill(v.begin(), v.end(), my_struct(4,2));


Quoted for emphasis. Good job demonstrating std::fill, too ;)
Quote:Original post by Zahlman
That doesn't help if you're putting things in a container, though :)
Well, that's not entirely true:

struct my_struct { int x, y; };boost::array< my_struct, 4 > array = {    { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }};
I also agree about using constructors, except that you are always assigning 0 to x and y, and not the arguments.
struct my_struct {    int x, y;    my_struct(int x_s = 0, int y_s = 0) : x(x_s), y(y_s) {}};


I added the _s because I'm used to it and I'm not sure the scoping rules when doing this:

struct my_struct {    int x, y;    my_struct(int x = 0, int y = 0) : x(x), y(y) {}};


My heart says that shouldn't work. I mean, it might work, but it shouldn't as it just looks confusing to me.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

This topic is closed to new replies.

Advertisement