1

I have a struct like this:

struct MYSTRUCT {
    ....
};

if I create struct objects with a for loop like this:

for(int i = 0; i < 2; i++){
    MYSTRUCT *mystruct;
}

will mystruct be the same every time because of the same name? What's the difference between the code above and this code:

MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1; 

How can I create different struct objects in a simpler way?

MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1;
...
MYSTRUCT *mystruct99;
MYSTRUCT *mystruct100; 

If I do the way below, will all the struct pointers same or they are isolated from each other?

vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
    MYSTRUCT *mystruct;
    mystructs.push_back();
}
9
  • 4
    Your looking for the concept of "Array". Commented Mar 19, 2015 at 13:27
  • Take a step back. Do you need to use pointers to the structs at all? Why are you doing what you are doing? Commented Mar 19, 2015 at 13:27
  • I do not think a pointer is what you want. If you were newing that memory yes every one would be unique the name does not matter. Though JBL is right what you are looking for is called a Array. Or a list/vector. Commented Mar 19, 2015 at 13:28
  • @JBL Well, a collection of some sort. Commented Mar 19, 2015 at 13:28
  • 1
    BTW, you are not creating structures in either example. You are creating uninitialized pointers. Commented Mar 19, 2015 at 13:29

5 Answers 5

6

First off, you should never try to generate variable names. it's just not the way to do it.

You should use a container (like in your example a std::vector) which is exactly what you want : something to put several other things of the same type.

In your example :

struct MyStruct {  // Don't name your struct in all caps.
                   // it's generally reserved for MACROS. Use CamelCase
    // blablabla

}

Do not use pointers unless you need to, usually it is much easier and much more efficient to use values. If you need to pass one of the elements of your vector to a function, so this function can modify it, you can pass an iterator to that element.

vector<MyStruct> mystructs;
for(int i = 0; i < 100; i++){
    mystructs.emplace_back(MyStruct{});
}

Also if your struct has fields that need to be initialized, you might want to use an initializer list or define a constructor.

If you need to use dynamic allocation you can do something like this :

vector<MyStruct*> mystructs;
for(int i = 0; i < 100; i++){
    mystructs.emplace_back(new MyStruct{});
}

Now the vector contains the pointers, not the objects. Each object is allocated individually in his own memory emplacement, therefore there is no garantee that they are next to each other. This matters tremendously for performance : Pointers give you indirection. Indirection leads to pain. Pain leads to anger ... blablabla => Welcome to the dark side.

Sign up to request clarification or add additional context in comments.

Comments

1

A struct is a datatype that you defined, when you do MYSTRUCT *mystruct you declare a pointer to a MYSTRUCT object and the pointer is called mystruct It is the same thing you do with int *pointer_to_int.

For you first version, you redeclare mystruct at each iteration while your second declares two independant variables. If you want to declare a set of MYSTRUCT* easily, use an array of MYSTRUCT*: MYSTRUCT* mystruct_pointers_array[100].

NOTE MYSTRUCT* pointers are different than MYSTRUCT variables, you need to dereference the pointer to access to MYSTRUCT elements. E.g. mystruct->x.

Comments

1

In your example code:

for(int i = 0; i < 2; i++){
    MYSTRUCT *mystruct;
}

You're not creating objects at all. All you're doing is declaring pointers to MYSTRUCT. These pointers are uninitialized and therefore don't point to anything (yet). Moreover, the pointer (mystruct) itself is allocated on the stack and has a lifetime limited to the scope of your for-loop.

I am not sure what you are trying to achieve, but if you need multiple objects of type MYSTRUCT, you should not try to create them in a loop like that. Rather, declare an array or std::vector and initialize appropriately. I will leave it to you to figure out how to do this. When you do, be aware of the difference between static and dynamic arrays, and their consequences for memory management!

EDIT: On request, I'll elaborate on the final snippet you provided:

vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
    MYSTRUCT *mystruct;
    mystructs.push_back();
}

What happens here is you declare an empty vector of pointers to MYSTRUCT. So far so good. Now, judging on the body, you want to populate this vector with pointers to actual objects, but this is not happening in your code. I doubt this will even compile, given that push_back requires a MYSTRUCT* as an argument. Therefore, to do what you intend to do, your code should in each iteration:

  1. Allocate an object on the heap.
  2. Push a pointer to this object to the back of the vector.

This would look like the following:

vector<MYSTRUCT*> vec;
for (int i = 0; i != n; ++i) // pre-incr is good practice!
    vec.push_back(new MYSTRUCT); // optionally add constructor arguments 

However, this introduces you to new responsibilities: you are the one requesting the memory explicitly using new, so you should free the memory explicitly using delete. Unless MYSTRUCT is polymorphic (contains virtual members), you can easily circumvent this (even it it is polymorphic, you shouldn't do this, but that's another topic).

The answer to this problem is: don't store pointers, store objects:

vector<MYSTRUCT> vec; // no pointer!
for (int i = 0; i < 100; ++i)
    vec.push_back(MYSTRUCT()); // create an unnamed instance and copy to the back of the vec

There, you have just created a vector of n MYSTRUCT instances. No pointers, no new and delete, simple and easy!

1 Comment

could you explain a little bit my last question?
0

Use a std::vector for this purpose:

std::vector<MYSTRUCT *> v(100);
for (auto& pointer : v)
   pointer = new MYSTRUCT(/*...*/); //initializating (writing address to pointer)

In your way you just initializing a object of pointer type. In other words you allocating memory only for pointer, where you must write address to your structure or nullptr-value.

5 Comments

I think it's dangerous to point an obvious novice (no disrespect intended) towards allocating objects on the heap using new and storing these pointers in a vector. A better alternative would be to store the objects directly in a vector and let that worry about resource management instead.
Your example won't compile if you declare pointer as a const reference.
@JorenHeit I am rather a novice too. I'll keep in mind it, thanks. But what if we'll use the vector of unique_ptr-s && make_unique in this case?
@François Moisan fixed, i get used to it.
You should at least mention deleting all elements. Moreover, there's really no need for storing pointers (unless OP wants to use polymorphism, but I doubt it), as vector already dynamically allocates it's elements. Having this, std::vector::reserve() and std::vector::emplace_back I don't see any need for using new manually.
0

Others have said similar things to this, but specifically I'd do it like this:

std::vector <MYSTRUCT *> vect;
for(int i = 0; i < 2; i++){
    vect.push_back();
}

Then you can just access each element like an array, like vect[0]. Plus with std::vector you can access the first element (element 0) with vect.front() and the last with vect.back().

Though it's useless without assigning a MYSTRUCT that has been initialized separately, I can see the usefulness of struct * vectors.

4 Comments

this doesn't really make any sense.
First of all, It won't compile (empty push_back()). Secondly, even if it would (and used default constructor), then why not just initialize vector with default elements? Lastly, you didn't mention need of using new and delete nor proposed smart pointers or not using any pointers at all.
Riiight, I had an idiot moment with regards to push_back(). I assumed the number of elements in the vector would need to be chosen after it was initialized, although using default elements would make more sense otherwise. How would you avoid using pointers when storing a reference to an object?
@zoska Ok, you're right, it doesn't make any sense. I realize now that if storing references to objects, you'd assign the pointers individually, not in a for loop. Which is likely not what they wanted to do.

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.