1

I would like to create a vector of pointers to struct

vector<myStruct*> vec

For elements in the vector, not all of them contain data. Some of them may point to NULL. So, should I create space by new in each of the element first

for(int i = 0; vec.size() ;i++){
       if (thisSpaceIsValid(i))
             vec.at(i) = new myStruct;
         else
             vect.at(i) = NULL;
}

The problem comes:
-If I use new for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector(vec here)?

-If later I use delete to free the memory, would the problem of speed still bother me?

roottraveller
  • 7,942
  • 7
  • 60
  • 65
Carl
  • 105
  • 3
  • 12
  • 2
    It may be a good opportunity for you to learn about smart pointers: http://en.cppreference.com/w/cpp/memory/shared_ptr. If you're using a pre-C++11 compiler you have the same functionality from the boost libraries. – Alain Jan 06 '16 at 17:09
  • "If I use new for each element, it would be very slow." *What* would be slow? Initializing the vector? Using it? – Nicol Bolas Jan 06 '16 at 17:10
  • you can still declare a `myStruct tab[max]` if you want to boost the performance but free memory could be delicate then – 88877 Jan 06 '16 at 17:12
  • If separate allocations is a concern for you, use your own allocation scheme... – Karoly Horvath Jan 06 '16 at 17:13
  • Are you sure that performance of dynamic memory allocation itself is something you should worry about? – SergeyA Jan 06 '16 at 17:30
  • Belt and suspenders programming: the loop runs from 0 to `vec.size()`, so the index `i` will always be in range. But the code also uses `at(i)` in order to make sure? – Pete Becker Jan 06 '16 at 20:42
  • @Alain Actually I simplify it, I do use `shared_ptr` – Carl Jan 07 '16 at 11:53
  • @NicolBolas I notice when operator `new` used repeatedly in code, it actually slow down the whole code. – Carl Jan 07 '16 at 11:54

4 Answers4

3

If I use "new" for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector("vec" here)?

You can do that.

Let's say the size of your vector is M and you only need N of those elements to have pointers to objects and other elements are null pointers. You can use:

myStruct* objects = new myStruct[N];

and then, use:

for(int i = 0, j = 0; vec.size(); i++)
{
   if (thisSpaceIsValid(i))
   {
      if ( j == N )
      {
         // Error. Do something.
      }
      else
      {
         vec[i]  = objects+j;
         ++j;
      }
   }
   else
   {
      vect[i] = NULL;
   }
}

You have to now make sure that you are able to keep track of the value of objeccts so you can safely deallocate the memory by using

delete [] objects;

PS

There might be a better and more elegant solution to your problem. It will be worth your while to spend a bit more time thinking over that.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Is it safe to work with structures in such manner? What's about padding? – Edgar Rokjān Jan 06 '16 at 17:22
  • @EdgarRokyan, of course it is safe. The compiler will take care of padding. – R Sahu Jan 06 '16 at 17:22
  • 3
    While this is elegant, it leaves us with terrible dilemma of safe and consistent pointer cleanup. – SergeyA Jan 06 '16 at 17:35
  • @SergeyA, I agree. There might be a more elegant solution to the OP's real problem. – R Sahu Jan 06 '16 at 17:43
  • @RSahu, How to create an array similar to `myStruct* objects = new myStruct[N];` with the use of `shared_ptr` instead of ordinary pointer? – Carl Jan 07 '16 at 11:52
  • @Carl, use of `shared_ptr` with arrays is not straight forward. See http://stackoverflow.com/a/8947700/434551. – R Sahu Jan 07 '16 at 16:21
1

EDIT:

After reading the question again, it seems I misunderstood the question. So here is an edited answer.

If you only need to execute the code during some kind of initialization phase, you can create all the instances of myStruct in an array and then just point to those from the vector as already proposed by R Sahu. Note that the solution requires you to create and delete all instances at the same time.

However, if you execute this code several times and/or don't know exactly how many myStruct instances you will need, you could overwrite new and delete for the struct and handle memory allocation yourself.

See Callling object constructor/destructor with a custom allocator for an example of this. See the answer by Jerry Coffin.

BTW - you don't need vec.at(i) as you are iterating from 0 to size. vec[i] is okay and should perform a better.

OLD ANSWER:

You can do

vector<myStruct*> vec(10000, nullptr);

to generate a vector with for instance 10000 elements all initialized to nullptr

After that you can fill the relevant elements with pointer to the struct.

For delete just

for (auto e : vec) delete e;

cause it is safe to do deleteon a nullptr

Community
  • 1
  • 1
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • As I can understand from the question the problem is the numerous usage of `new` and it's impact to performance. Your answer isn't really helpful in this case. – Edgar Rokjān Jan 06 '16 at 17:18
  • @EdgarRokyan - after reading the question again I think your are right. It seems I simply misunderstood the problem. Sh.. happens. – Support Ukraine Jan 06 '16 at 17:30
0

If you need a vector of pointers, and would like to avoid calling new, then firstly create a container of structs themselves, then assign pointers to the elements into your vec. Be careful with choosing the container of structs. If you use vector of structs, make sure to reserve all elements in advance, otherwise its elements may move to a different memory location when vector grows. Deque on the other hand guarantees its elements don't move.

Multiple small new and delete calls should be avoided if possible in c++ when performance matters a lot.

0kcats
  • 672
  • 5
  • 16
0

The more I think about it, the less I like @RSahu's solution. In particular, I feel memory management in this scenario would be a nightmare. Instead I suggest using a vector of unique_ptr's owning memory allocated via custom alloctor. I believe, sequential allocator would do.

SergeyA
  • 61,605
  • 5
  • 78
  • 137