1

For my project I need to store pointers to objects of type ComplicatedClass in an array. This array is stored in a class Storage along with other information I have omitted here.

Here's what I would like to do (which obviously doesn't work, but hopefully explains what I'm trying to achieve):

class ComplicatedClass
{
    ...
}


class Storage
{
    public:
        Storage(const size_t& numberOfObjects, const std::array<ComplicatedClass *, numberOfObjects>& objectArray)
            : size(numberOfObjects),
              objectArray(objectArray)
        {}

    ...

    public:
        size_t size;
        std::array<ComplicatedClass *, size> objectArray;
    
    ...
}


int main()
{
    ComplicatedClass * object1 = new ComplicatedClass(...);
    ComplicatedClass * object2 = new ComplicatedClass(...);
    Storage myStorage(2, {object1, object2});
    
    ...
    
    return 0;
}

What I am considering is:

  1. Using std::vector instead of std::array. I would like to avoid this because there are parts of my program that are not allowed to allocate memory on the free-store. As far as I know, std::vector would have to do that. As a plus I would be able to ditch size.
  2. Changing Storage to a class template. I would like to avoid this because then I have templates all over my code. This is not terrible but it would make classes that use Storage much less readable, because they would also have to have templated functions.

Are there any other options that I am missing?

Agiltohr
  • 115
  • 5
  • 6
    I'm not really sure what you mean by "free-store", but you can pass an allocator to `std::vector` which is used to allocate the memory it needs internally. Such an allocator can be made to allocate memory wherever you need – UnholySheep Dec 21 '21 at 20:48
  • @UnholySheep Oh, right! I totally forgot about that. I have to look into that, thanks! I thought C++ had "free-store" instead of heap, does it not? – Agiltohr Dec 21 '21 at 20:49
  • Heap is an implementation, by far the most common, of the free store. – user4581301 Dec 21 '21 at 20:49
  • Oh, right. I forgot that the standard refers to it that way (I've yet to work on a platform where the free-store is something different than the heap, so I completely forgot about that name) – UnholySheep Dec 21 '21 at 20:53
  • I've only seen non-heap free stores in the hands of academics. If any managed to escape into the wild, they were outcompeted and didn't get a chance to breed and destabilize the ecosystem. – user4581301 Dec 21 '21 at 21:27

2 Answers2

2

How can I pass and store an array of variable size containing pointers to objects?

By creating the objects dynamically. Most convenient solution is to use std::vector.

size_t size;
std::array<ComplicatedClass *, size> objectArray;

This cannot work. Template arguments must be compile time constant. Non-static member variables are not compile time constant.

  1. I would like to avoid this because there are parts of my program that are not allowed to allocate memory on the free-store. As far as I know, std::vector would have to do that.

std::vector would not necessarily require the use of free-store. Like all standard containers (besides std::array), std::vector accepts an allocator. If you implement a custom allocator that doesn't use free-store, then your requirement can be satisfied.

Alternatively, even if you do use the default allocator, you could write your program in such way that elements are inserted into the vector only in parts of your program that are allowed to allocate from the free-store.

I thought C++ had "free-store" instead of heap, does it not?

Those are just different words for the same thing. "Free store" is the term used in C++. It's often informally called "heap memory" since "heap" is a data structure that is sometimes used to implement it.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

Beginning with C++11 std::vector has the data() method to access the underlying array the vector is using for storage.

And in most cases a std::vector can be used similar to an array allowing you to take advantage of the size adjusting container qualities of std::vector when you need them or using it as an array when you need that. See https://stackoverflow.com/a/261607/1466970

Finally, you are aware that you can use vectors in place of arrays, right? Even when a function expects c-style arrays you can use vectors:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • 1
    `std::vector` has always had a contiguity guarantee, making `&v[0]` usable anywhere a pointer is needed (it's not new with C++11). And that remains a better option than `data()`, because it works on both vectors and strings. – Ben Voigt Dec 21 '21 at 22:10
  • The underlying array of the vector would still be allocated on the heap, right? Unless I use a custom allocator. – Agiltohr Dec 21 '21 at 22:12
  • @Agiltohr yes the underlying array would still be located where ever the `std::vector` allocator is using to allocate memory. I'm curious why the memory location where the array is allocated matters. Can you provide details about this requirement in your posted question by editing it? It sounds like parts of your application are free to do so and others aren't. Is this some type of safety standard to prevent an out of memory event on an allocation causing an application crash or something else that you could explain? You can treat a `std::vector` as an array when you need to or as a container. – Richard Chambers Dec 22 '21 at 02:01
  • 1
    @RichardChambers It is a realtime context for audio processing. It is typical that heap allocations during the processing is prohibited, one needs to do any necessary allocations beforehand because allocations on the heap are too slow. I need to pass around some objects (that I've allocated before the processing started) to functions but which objects and how many I need to pass may be chosen at runtime. I could allocate the vectors of all possible combinations on the heap beforehand but that doesn't seem very practical. – Agiltohr Dec 22 '21 at 02:08
  • @Agiltohr With `std::vector` you can use the container methods to pre-allocate a vector of the size needed on the heap or free store and then use the resulting vector as an array where ever you need it without having to do any more allocations. And you can probably pick times to resize the vector when using the heap or free store will not matter. Or you can write your onw allocator for speed. I'm curious if you have written your own version of `new` for object construction? – Richard Chambers Dec 22 '21 at 18:31
  • @RichardChambers The issue is that the contents of the vector might change so I might need to have multiple different vectors for all the possible combinations of contents. This is not very scalable so I need to at least have a fallback for situations where the contents of the vector need to be determined at runtime, when no allocations on the heap are allowed. No, I've not written my own version of ```new```, all necessary objects I allocate before the realtime processing starts. – Agiltohr Dec 22 '21 at 18:51