3

I am using a boost::ptr_vector over just std::vector as it will handle the deletion of all of the pointers for me. However when I do:

ptr_vector<SoftLabelRandomTreeFunctor> functors;
functors.resize(number_of_functors);

It complains that SoftLabelRandomTreeFunctor does not have a default constructor. However, I was under the impression that it would just need to resize big enough to fit number_of_functors * the size of a pointer to a SoftLabelRandomTreeFunctor, not number_of_functors * the size of a SoftLabelRandomTreeFunctor itself?

Aly
  • 15,865
  • 47
  • 119
  • 191
  • When you increase the size, new pointers are added to the vector *and* initialized with addresses of new objects. – n. m. could be an AI Nov 14 '12 at 16:58
  • The point is that is simply makes no sense to resize the container if you don't want to put anything inside. You can just use `reserve` to preallocate the memory if you know you are *going to* insert some elements. – Kerrek SB Nov 14 '12 at 17:02
  • @KerrekSB The reason I am resizing is because I want to be able to assign to the vector in a random manner, i.e. set poisition 1, and then 0. So functors.replace(1,obj1); functors.replace(0,obj2); so I resize to ensure that I will no go out of bounds – Aly Nov 14 '12 at 17:06
  • @Aly: Can't you use `push_back`s instead? Or use a different container, like `std::vector>`, which seems more suitable to what you want to do. The `boost::ptr_vector` is a very specific container for a very specific use case, which doesn't seem to suit yours. Since you explicitly *want* pointers, you should *have* pointers in your visible design. – Kerrek SB Nov 14 '12 at 17:14
  • @KerrekSB push_back does sequential inserts, i.e. the first call will put the item at position 0, the second will put it at position 1. I want to assign to position 1 first, then position 0 (as you would be able to with an array of fixed size) – Aly Nov 14 '12 at 17:15
  • Yes, I know... I've updated the previous comment. The upshot is: use a different container. – Kerrek SB Nov 14 '12 at 17:18

2 Answers2

3

I am not really experienced with Boost, so take my answer with a grain of salt. However, skimming through the docs for boost::ptr_vector made me think that what you want (as follows from the comments to the question) should be possible to do this way:

boost::ptr_vector< boost::nullable<SoftLabelRandomTreeFunctor> > functors;
functors.resize(number_of_functors, 0);

The references for you to read and make your own conclusion:

Alexey Kukanov
  • 12,479
  • 2
  • 36
  • 55
1

When you write functors.resize(number_of_functors) you potentially increase the size of the vector to contain number_of_functors elements inside. Since ptr_vector by default disallows storing NULL values, it needs to put a meaningfull data into the inflated array. The function intends to call new SoftLabelRandomTreeFunctor() for every new element and it requires a default constructor for that.

If you want to allow NULLs, you need the boost::nullable as suggested by Alexey Kukanov answer, and as in the tutorial included in the manual ((here)).

However, if you just intend to reserve enough memory for number_of_functors elements without semantically creating them and without increasing the array size --- you don't need nullable and you should call instead:

functors.reserve(number_of_functors)

Note that after this, you still need to increase the array size when you put new elements (e.g. via push_back). You will have a guarantee though that push_back won't call a memory reallocation as long as your size doesn't exceed number_of_functors.

CygnusX1
  • 20,968
  • 5
  • 65
  • 109