user6813120
user6813120

Reputation:

c++ right way to initialize a vector of a struct

i searched a lot here, but there is no right explanation for me, for an advanced newbie in c++. I worked before with vector of structs and now I get segmentation faults...

Thats why I want to know how such objects actually works and if it is the right the way I am doing!

I have a struct like

struct numberOfSpecies {
   int predator;
   int prey1;
   int prey2;
};

and a vector of it:

std::vector<numberOfSpecies> size;

Before I resize it and fill it with values.

size.resize(100);

what is actually this doing? Is this right for a struct? It looks like it is initialized with zeros...

Now I am doing this like:

size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;

for(int k = 0; k < N; ++k){
  size[t].predator++;
  size[t].prey1++;
  size[t].prey2++;
}

Is this right? Where are possible issues? How to do it better?

Upvotes: 2

Views: 5973

Answers (4)

Anders Cedronius
Anders Cedronius

Reputation: 2076

Use the value parameter for static parameters.

#include <vector>

struct foo{
    int g;
    int h;
    int l;
};

int main()
{
    std::vector<foo> manyFoo(10, {0});
    manyFoo.resize(60, {0});
} 

If you want to grow your vector as you also put arbitrary values into the struct you could ->

#include <iostream>
#include <vector>

struct foo{
    foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
    int g;
    int h;
    int l;
};

int main() {
    std::vector<foo> lVec;
    for (int i=0;i<10;i++) {
        lVec.emplace_back(foo(i,i*2,i*4));
    }
    int lPos=0;
    for (auto &rFoo: lVec) {
        std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
    }
    return EXIT_SUCCESS;
}

If you know the size of the vector and you want to populate it you could ->

#include <iostream>
#include <vector>

struct foo{
    foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
    int g;
    int h;
    int l;
};

int main() {
    std::vector<foo> lVec(10,{0,0,0});
    int lPos = 0;
    for (auto &rFoo: lVec) {
        rFoo = foo(lPos,lPos*2,lPos*4);
        lPos++;
    }
    lPos=0;
    for (auto &rFoo: lVec) {
        std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
    }
    return EXIT_SUCCESS;
}

Upvotes: 0

This:

size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;

will write zeros to the tth element of size - that may or may not be useful:

This:

for(int k = 0; k < N; ++k){
  size[t].predator++;
  size[t].prey1++;
  size[t].prey2++;
}

will increment the tth element of size N times. This seems incredibly unlikely to be useful. I think what you want is:

size[0].predator=0;  // Technically not needed because .resize()
size[0].prey1=0;     // will have initialized it to zero anyway
size[0].prey2=0;     // *BUT* explicit is always better than implicit.

// Initialize each element of size to be one greater than previous.
for(int k = 1; k < N; ++k){
  size[k].predator = size[k-1].predator + 1;
  size[k].prey1    = size[k-1].prey1    + 1;
  size[k].prey2    = size[k-1].prey2    + 1;;
}

Upvotes: 1

George
George

Reputation: 2120

The easiest and 'correct' solution here is probably to just use the resize() function that belongs to the vector object with aggregate initialization (if you have access to c++11 and on), something like

size.resize(100,{0,0,0}); //aggregate initialization 

for(int k = 0; k < N; ++k)
{
    size[t].predator++;
    size[t].prey1++;
    size[t].prey2++;
}

All members of each numberOfSpecies object will be initialized to 0.

Upvotes: 3

Ionut V.
Ionut V.

Reputation: 110

You could add an default constructor to your structure. The new code will look something like this:

struct numberOfSpecies {
    numberOfSpecies (): predator(0), prey1(0), prey2(0) { }  // default constructor
    int predator;
    int prey1;
    int prey2;
};

That way, your structure will be properly initialized inside your vector when resize is applied.

Upvotes: -1

Related Questions