user2327195
user2327195

Reputation: 263

C++ Proper Methodology for vectors of structs

So imagine I have a struct

struct Square{
  int width;
  int height;
};

Then i have a function somewhere in my code

void create_vec_squares(std::vector<Square> &dest){  
    for(int i = 0; i < 10; i++){
        //create squares and put then into the destination vector
    }
}

What is considered the proper way to do this in C++? I know some C, and my immediate thought is to use memory allocation techniques such as malloc. But, i will need to throw in a void delete_vec_squares(...) to make sure the memory is properly freed.

I was wondering if any issues could arise with this method

void create_vec_squares(std::vector<Square> &dest){
    for(int i = 0; i < 10; i++){
        int val1,val2;
        //generate some values for squares
        ...
        //end generation
        dest.push_back({val1, val2});
    }
}

From my understanding, instead of allocating memory on the heap, the structures will simply be pushed onto the stack and there will be no need for manual memory allocation techniques;

Upvotes: 1

Views: 95

Answers (4)

Aleksey F.
Aleksey F.

Reputation: 761

If you exactly know that ten objects are to be set in dest, the following approach may be cleaner and faster:

struct Square{
  int width;
  int height;

  Square & set(int p_width, int p_height) {
      width = p_width; height = p_height;
      return (*this);
  }
};

typedef std::vector<Square> Square_vec;
void create_vec_squares(Square_vec & dest){  
    //create squares
    dest.reasize(10);
    for(Square_vec::iterator v_i = dest.begin(), v_e = dest.end(); v_i < v_e; ++v_i){
        // and put then into the destination vector
        v_i->set(val1, val2); //The already created Square object is set whithout temporary.
        //Or if you have common temporay Square object:
        *v_i = tmpSquare;
    }
}

Next step of refactorring may be creating a functor for filling up Square_vec substituted into the for_each function from <algorithm> instead of the for(Square_vec::iterator ... loop.

Upvotes: 0

David Hammen
David Hammen

Reputation: 33106

I was wondering if any issues could arise with this method

void create_vec_squares(std::vector<Square> &dest){
    for(int i = 0; i < 10; i++){
        int val1,val2;
        //generate some values for squares
        ...
        //end generation
        dest.push_back({val1, val2});
    }
}

The only issue with this method is that your code might not be portable. Some places are still stuck with C++03 compilers, which doesn't have uniform initialization.

With regard to the proper methodology, there is no one proper methodology. Uniform initialization is great when you can use it. You can't always use it (even in C++11 and higher). Sometimes you need to use an explicit constructor, sometimes you need to operate on the item before adding it to the container. There's still no need for new and delete. Just declare a local variable and push that back onto the container.


When you know you are going to drop a boatload of objects onto a vector, it can be advantageous to reserve some space for that incoming boatload. Your code with a boatload (10000) objects instead of just 10:

void create_vec_squares(std::vector<Square> &dest){
    dest.reserve(dest.size() + 10000);
    for(int i = 0; i < 10000; i++){
        int val1,val2;
        //generate some values for squares
        ...
        //end generation
        dest.push_back({val1, val2});
    }
}

Upvotes: 0

Dean Seo
Dean Seo

Reputation: 5683

instead of allocating memory on the heap, the structures will simply be pushed onto the stack and there will be no need for manual memory allocation techniques;

You are right. When you push_back, you just need to push_back, because

std::vector<T>::push_back(const T & val);

is copy-based.

Your Square object will be safely kept in std::vector<Square> out of scope.

If you do some allocation in Square, then it's Square::~Square()'s job to free what's needed to be.

Upvotes: 1

Ediac
Ediac

Reputation: 853

push_back is a vector method that adds a new element at the end of the vector, after its current last element.

You can do the following:

void create_vec_squares(std::vector<Square> &dest){  
    for(int i = 0; i < 10; i++){
        //create an object Square and lets call it newSquare, then you can use push_back
        dest.push_back(newSquare); 
        //this will add your object newSquare at the end of vector dest
    }
}

And if you want to empty the vector entirely, you can use dest.clear().By using the included methods it decreases the chances of mismanaging an object vector and is generally safer.

Upvotes: 0

Related Questions