Sign in to follow this  

quick question on STL / vector container

This topic is 3933 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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[i].xxxxx = 0; objects[i].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[i], 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?

Share this post


Link to post
Share on other sites
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[i] = tmp;

Share this post


Link to post
Share on other sites
You could also just write a constructor for the struct that initializes the variables. vector will then call that constructor when inserting the elements.

Share this post


Link to post
Share on other sites
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));

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ;)

Share this post


Link to post
Share on other sites
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 } }
};

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by nobodynews
struct my_struct {
int x, y;
my_struct(int x = 0, int y = 0) : x(x), y(y) {}
};


Actually, it works exactly as expected : the argument overshadows the member wherever it is present. From my experience, this version (without the warts) is quite idiomatic in these situations. It doesn't happen very often that you need to initialize a member from another member and that there is such a clean argument-to-member mapping.

Share this post


Link to post
Share on other sites

This topic is 3933 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this