0

Is there any way, to declare static array in class with size that was passed to constructor? It is alright if the size has to be const and it makes it impossible to set it in runtime.

I tried doing something like this:

class class_name
{
    public:
        float* map;
        class_name(int n, const int d)
        {
            float arr[d];
            map = arr;
        }
};

but I feel like it could be very bad idea. Is it bad? If it is, then why is it?

Crimsoon
  • 83
  • 8
  • 1
    That's not a `static`. – Stephen Newell Mar 31 '22 at 16:46
  • Two reasons: [Standard C++ does not support Variable length arrays](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) and `arr` is an automatic variable scoped by the constructor. [As soon as the constructor exits, it's no longer valid](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope). – user4581301 Mar 31 '22 at 16:46
  • So please clarify what you mean by static array. It seems like you don't actually mean static, but something else. – hyde Mar 31 '22 at 16:53
  • 2
    A static array needs its size to be known at compile time. What you did is not bad, but you should be careful with memory allocation/deallocation. You are using a dynamic array. You are better off using a `std::vector` instead. – Ari Mar 31 '22 at 16:54
  • The code you show here is indeed wrong. `arr` is a local variable. Setting `map` point to it creates a dangling pointer, when the constructor returns. What are you trying to achieve here? – hyde Mar 31 '22 at 16:54
  • @Ari What the code now does _is_ bad, `map` becomes a dangling pointer... Not to mention, it is not standard C++ (because it uses VLA). – hyde Mar 31 '22 at 16:55
  • @hyde by static, I meant not dynamic. I'd like to make an array at compile time, in an object made at compile time, by passing size of array as `const` into constructor. Edit: or not necessarily passed into constructor. It can be passed any way, just the way it would work. – Crimsoon Mar 31 '22 at 17:03
  • @hyde Oh I just noticed this. I thought a dynamic array is constructed using new. So, yes this is bad! – Ari Mar 31 '22 at 17:11
  • @Crimsoon Then `std::array` is what you want. Just make your own class a template as well. – hyde Mar 31 '22 at 17:12
  • `template class class_name { public: std::array map; ....`. In constrctor, zero it out with `std::fill(map.begin(), map.end(), 0);` – hyde Mar 31 '22 at 17:15
  • @hyde also, why does map become a dangling pointer? Is memory used by local variables in constructor freed as constructor returns? – Crimsoon Mar 31 '22 at 17:16
  • @Crimsoon Yes, local variables cease to exist when the block they are defined in (in this case the constructor body) ends. – hyde Mar 31 '22 at 17:17
  • @hyde thanks for answering and sorry for asking unclear question. I didn't know how to make it more precise :// – Crimsoon Mar 31 '22 at 17:21
  • I don't quite understand what do you mean. Should I comment what you wrote? – Crimsoon Mar 31 '22 at 17:23

2 Answers2

2

Yes, this code

    class_name(int n, const int d)
    {
        float arr[d];
        map = arr;
    }

is a bad idea, for 2 reasons

  1. float arr[d]; creates a local variable in stack, so it ceases to exist at the end of the block. So map becomes a dangling pointer. If you needed dynamic size allocation, you should just use std::vector<float> map and avoid a lot of hassle.
  2. float arr[d]; is a variable length array, and C++ does not support those. Making d be const does not help, it has to be an actual constant, not const variable.

Solution: Since you say the array length can be determined at compile time, this is perfect fit for a template:

template <std::size_t N>
class class_name
{
    public:
        std::array<float, N> map { {} }; // { {} } causes value initialization of everything to 0
        // actually above could be `float map[N];` but it has the C array gotchas
        
        class_name(int n)
        {
            // not sure what n is for...
        }
};

And to declare a variable of this class:

class_name<5> obj; // obj.map size is 5
hyde
  • 60,639
  • 21
  • 115
  • 176
-3

By 'static array', do you mean something of unchanged size? std::unique_ptr<float[]>, and std::make_unique(std::size_t), might be an option.

bipll
  • 11,747
  • 1
  • 18
  • 32
  • 3
    This looks more like a comment than an answer. – user4581301 Mar 31 '22 at 16:49
  • By static, I mean (it may not be the right term for it) array that doesn't dynamicaly allocate memory. I set it's size as I want to declare and initialize it as I declare an object of the class it's in. – Crimsoon Mar 31 '22 at 16:55
  • @Crimsoon a fixed-sized array must have its size specified directly in its declaration at compile-time. You are trying to separate the size from the declaration, and that can only work with a dynamic array – Remy Lebeau Mar 31 '22 at 18:29