0

I want to malloc an array in my code, and its size should be defined at runtime.

I tried like this:

#include <iostream>
#include <array>

int main(){
    int M=4,N=3,P=5;
    M=N+P;
    std::array<std::array<double,M>,N> arr;
}

But MSVC told me:

a variable with non-static storage duration cannot be used as a non-type argument

I don't find the answer to this in stackoverflow.(The existing question seem not to solve my problem...)

How to dynamically allocate a 2D std::array in C++?

I know I could use std::vector to solve this. But the vector memory size needs to be organized by myself and this would be used many times in my project. And I want to use C++ type code rather than C type...Maybe there is a method to turn a 2D array in C type to std::array, but I can't find it by Google...

So I ask this question...

I mean the M and N should be got dynamically(not changed,but I can only know it in runtime...),like:

#include <iostream>

int main(){
    int a=3;
    int b=4;
    int rowCount=a+b;
    int colCout=b-a;
    int** a = new int*[rowCount];
    for(int i = 0; i < rowCount; ++i)
    {
        a[i] = new int[colCount];
    }
}

I know where is my mistake. I fell into a logical question... If I don't use push_back,the vector works well. If I use it, the array doesn't work, too.

I think the capcity of vector is bigger than its size, I want to avoid this. But another question: How to limit the capacity of std::vector to the number of element show I should use my allocator or std::vector::shrink_to_fit() to avoid it...(There is no guarantee in C++17 if you use reserve(n))

Learning Lin
  • 121
  • 1
  • 7
  • 1
    You want a std::vector. std::array is a fixed size at compile time. – drescherjm Apr 10 '22 at 14:31
  • 1
    If you want to use C++ type code instead of C code for handling containers whose size isn't known until run time, you want to use std::vector. I don't understand the question. – Nathan Pierson Apr 10 '22 at 14:31
  • 3
    The `std::vector` is the right solution. *"But the vector memory size need to organize by myself"* I don't understand what you're trying to say. – HolyBlackCat Apr 10 '22 at 14:31
  • 1
    ***I mean the M and N should be got dynamically(not changed,but I can only know it in runtime...)*** Then you will need a std::vector and not std::array. – drescherjm Apr 10 '22 at 14:36
  • Maybe you need to show why you think a std::vector won't work for your problem. I think this is a bit of a XY problem. – drescherjm Apr 10 '22 at 14:42
  • @drescherjm Because the vector memory size is bigger than the same array if I don‘t control by myself, I think I should get it in constructor... – Learning Lin Apr 10 '22 at 14:43
  • Maybe you want to allocate a 1D vector and use a matrix class – drescherjm Apr 10 '22 at 14:44
  • @LearningLin that makes no sense. `std::vector` will get you exactly the memory you need. – Marcus Müller Apr 10 '22 at 14:44
  • @drescherjm I will get vector.capacity() in the "fine_vector" constructor – Learning Lin Apr 10 '22 at 14:44
  • @LearningLin what? That makes no sense. – Marcus Müller Apr 10 '22 at 14:45
  • @MarcusMüller I think you are right. I mean if I don't use push_back, the memory size should be I want. Thank you. – Learning Lin Apr 10 '22 at 14:48
  • there's a constructor of `std::vector` with which you can specify the exact size, see (3) in the list at [cppreference](https://en.cppreference.com/w/cpp/container/vector/vector) - (edit also [mentioned in answer by Marcus Müller](https://stackoverflow.com/a/71817560) I just saw) – codeling Apr 10 '22 at 14:51
  • @drescherjm Yes, this is a X-Y problem. – Learning Lin Apr 10 '22 at 15:12

2 Answers2

7

The dynamically allocated array container in C++ is std::vector. std::array is for specifically compile-time fixed-length arrays.

https://cppreference.com is your friend!

But the vector memory size needs to be organized by myself

Not quite sure what you mean with that, but you specify the size of your std::vector using the constructor.

std::vector<std::vector<int>> arr(N);

If you need some special allocator (not just new/malloc), then you can also specify a custom allocator.

Your whole program that you propose is not good C++. A C++ solution would look like:

#include <vector>
int main() {
    int a = 3;
    int b = 4;
    unsigned int rowCount = a + b;
    unsigned int colCount = b - a;
    std::vector<std::vector<int>> matrix(rowCount);
    for (auto& row : matrix) {
        row.resize(colCount);
    }
}
Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • Ok, I get the point. I guess I should define a new type for it. – Learning Lin Apr 10 '22 at 14:40
  • 1
    @LearningLin I don't think that was the point – Ted Lyngmo Apr 10 '22 at 14:41
  • 3
    ...What? How is that your takeaway from this? – Nathan Pierson Apr 10 '22 at 14:41
  • 1
    @LearningLin no, that was not the point, at all. You don't need a new type. The existing `std::vector>` simply works. – Marcus Müller Apr 10 '22 at 14:42
  • @MarcusMüller I think you are right. I mean if I don't use push_back, the memory size should be I want. Thank you – Learning Lin Apr 10 '22 at 14:47
  • Is my answer right? I mean the capacity of vector may be bigger than vector. And I want to avoid it. In C++17, the other question show there is no method unless I use my allocator. Does it exit in C++20? – Learning Lin Apr 10 '22 at 15:08
  • 1
    I don't understand what you're asking me here. But if something existed in C++17, it will still exist in C++20. Also, you seem to think that overallocation is really bad, but it's not. If the memory pages allocated to the vector are not touched, they don't use physical memory. So, the most you're wasting could be a little less than 4 kB in RAM. Which you would also be wasting with `new` or `malloc`, you just don't notice. – Marcus Müller Apr 10 '22 at 15:12
2

std::array, like an actual array in C++, requires a constant size. It's what gives it any advantage at all over std::vector.

For a technical explanation as to how that requirement is implemented, remember that template parameters are required to be compile-time constants (since it changes how the code is generated, again at compile-time).

Anyway, you want to use std::vector here. If you know the size you want, give it as a constructor parameter.

Blindy
  • 65,249
  • 10
  • 91
  • 131