0

I am looking for the equivalent of .NET fixed size arrays in C++ and am having real trouble finding this information by Googling it. std::array imitates Pascal by having the length embedded directly in its type. std::vector is good, but passes around 3 pointers on the stack where I'd prefer just one.

Also rather than iterator based arrays, since I am working on a C++ backend for a functional language I'd prefer it to be size based so as too match the arrays in the .NET and the Cython backends.

Should I implement my own array class instead?

Edit: What I am asking for is a flexible array (such as this one) as a part of a library.

Marko Grdinić
  • 3,798
  • 3
  • 18
  • 21
  • `std::array` does not imitate Pascal in any way, it is just a wrapper for fixed-size C array. And it can be heap-allocated. – user7860670 Aug 28 '21 at 08:00
  • I don't know what you mean about Pascal but C-arrays also have the size embedded in their types. `int [3]` is not the same type as `int [4]`: https://godbolt.org/z/Khs9aG5z3 – mediocrevegetable1 Aug 28 '21 at 08:02
  • 2
    What do you mean by "around 3 pointers on the stack"? Vector often does have three pointers, but you can't just memcpy it like that. You will usually pass it by reference, which is usually implemented as a pointer. – Aykhan Hagverdili Aug 28 '21 at 08:07
  • Have you considered dynamically allocating a `std::array<>`? – Ulrich Eckhardt Aug 28 '21 at 08:14
  • @AyxanHaqverdili See [this question](https://stackoverflow.com/questions/30422205/why-the-libc-stdvector-internally-keeps-three-pointers-instead-of-one-pointe). I've also verified that `sizeof(std::vector)` is 24 in 64-bit mode and 12 in 32-bit mode, so I see no reason to doubt this. – Marko Grdinić Aug 28 '21 at 08:14
  • @UlrichEckhardt The problem with `std::array` is that it requires the size directly in its type as a constant value. I'd like the array to have its length determined at runtime. – Marko Grdinić Aug 28 '21 at 08:16
  • 3
    Three pointers or not, you don't pass them around. You either create a copy, which involves repeating the dynamic allocation and copying each element, so the three pointers are not an issue there. Or, you pass by reference, which amounts to one pointer. – Ulrich Eckhardt Aug 28 '21 at 08:16
  • 1
    Okay, so your question title is kind-of misleading. People read "fixed size", but you don't mean "fixed at compile time" but "fixed after allocation during execution time". Use a std::vector, perhaps dynamically allocated. Rolling your own containers is tedious with doubtable benefits. Get it correct first, then, with benchmarks and tests as a base, optimize it. – Ulrich Eckhardt Aug 28 '21 at 08:19
  • Well, that's the thing with fixed-size arrays in C++: size must be a compile-time constant because it is a part of the type. – user7860670 Aug 28 '21 at 08:19
  • @UlrichEckhardt If I pass them as a reference like that, that means they'd be in another heap allocated structure or glued to the stack which would break tail call optimization when I get to it later. Also in such a case, indexing into them would have to go through two pointers. Instead it should be possible to have a data structure in which the first element of the struct is the length and the rest is the array data. This would be ideal. – Marko Grdinić Aug 28 '21 at 08:24
  • 1
    Based on the comments so far, it's a good guess that the question should better explain the functional requirements. Currently, the question uses six words ("equivalent of .NET fixed size arrays") to describe the functional requirements before diving into why certain choices will not work. The ratio of word count for requirements to that for dismissing options should probably be reversed. – JaMiT Aug 28 '21 at 08:28
  • I'd also request a clarification of "iterator based arrays", as I thought iterators were how to access arrays rather than how to define them. Is "iterator based arrays" a standard term in this context? – JaMiT Aug 28 '21 at 08:29
  • 'iterator based arrays' refers to the structure of having a pointer to the start and the end of the array as opposed to having a pointer to the start and the size. – Marko Grdinić Aug 28 '21 at 08:33
  • 1
    From your question and all the comments so far, it seems you have some misconceptions about C++. First of all, heed the advice given, use a `std::vector`. Then learn about the basics of C++, especially passing parameters by value and by reference (or as pointers). – Olaf Dietsche Aug 28 '21 at 08:36
  • Here is one https://stackoverflow.com/q/2139224/1741542, maybe search for others [[c++] pass by value](https://stackoverflow.com/search?q=%5Bc%2B%2B%5D+pass+by+value) and [[c++] pass by reference](https://stackoverflow.com/search?q=%5Bc%2B%2B%5D+pass+by+reference). Be aware, there are many special cases, but you should get the idea. – Olaf Dietsche Aug 28 '21 at 08:43
  • @MarkoGrdinić You have provided useful information in the comments. I look forward to you editing that information into the question. – JaMiT Aug 28 '21 at 08:44
  • 1
    You could also take a look at [`std::span`](https://en.cppreference.com/w/cpp/container/span/span). It's a non-owning wrapper for a given range that you could pass around by value. – Lukas-T Aug 28 '21 at 11:16

1 Answers1

1

You can use unique_ptr:

#include <memory>

int main() {
  // note brackets  vvvv
  std::unique_ptr<int[]> arr{ new int[42] };
  arr[0] = 13;
  // ...
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • This does not allocate fixed-size array. – user7860670 Aug 28 '21 at 08:02
  • @user7860670 why not? It allocates an array which cannot be resized. – Aykhan Hagverdili Aug 28 '21 at 08:03
  • Allocating array of items is slightly different from allocating a single fixed-size array. Which is actually not supported at all, as far as i know. For example `using tp = int[42]; tp * p{new tp{}};` causes an error. – user7860670 Aug 28 '21 at 08:10
  • @user7860670 This does allocate an array, and returns a pointer to the first element. Otherwise it would be UB to index the pointer as `arr[42]`. Note that it is UB to do `p[n]` unless `p` and `p+n` are pointing to elements inside the same array. – Aykhan Hagverdili Aug 28 '21 at 08:15
  • @AyxanHaqverdili It should have a size embedded in it, either explicitly or implicitly via a pointer to its end. Also like for `std::vector` in Debug mode, it should do bounds checking during indexing and assignment. – Marko Grdinić Aug 28 '21 at 08:18
  • @MarkoGrdinić You want to store the size AND have the size of a single pointer? That is impossible (unless you store the size inside the dynamically allocated buffer). Otherwise, use `std::vector`, which does store the size. – Aykhan Hagverdili Aug 28 '21 at 08:20
  • It allocates array, but it is not a fixed size array type. And it is totally possible to store data and size using a single pointer, for example by prefixing data with size (that's what pascal-style strings do). – user7860670 Aug 28 '21 at 08:22
  • @user7860670 Yes, that is how .NET arrays work. That is what I am looking for. – Marko Grdinić Aug 28 '21 at 08:26
  • @MarkoGrdinić Then you'll need to implement it yourself. – user7860670 Aug 28 '21 at 08:27
  • @user7860670 the size is fixed, but at runtime, not compile time. If you want the size to also be dynamically allocated (not stored in the container), you need two separate allocations, because there is no standard C++ way to allocate a single buffer where (1) the first element is of a different type (2) is considered an array so indexing it is legal. In C language, you can use a "flexible array" but that is not standard C++. You can certainly get that working, it won't be confirming legal C++. – Aykhan Hagverdili Aug 28 '21 at 08:29
  • 1
    @user7860670 Please see [this video](https://youtu.be/IAdLwUXRUvg?t=1671) for more. – Aykhan Hagverdili Aug 28 '21 at 08:35
  • @AyxanHaqverdili Watched the part on flexible array members. Is there such an array implemented as a part of the library somewhere? This is what I've been looking for. – Marko Grdinić Aug 28 '21 at 09:41
  • @MarkoGrdinić if you want a heap array with an embedded size then can't you use `std::unique_ptr>`? – mediocrevegetable1 Aug 28 '21 at 10:13
  • @mediocrevegetable1 No, because I might not have the size known as a compile time constant. It is a huge restriction to require it. – Marko Grdinić Aug 28 '21 at 10:36
  • 1
    @MarkoGrdinić No, nothing in the standard library does that. How about something like [this](https://gcc.godbolt.org/z/E5e1EoM75) (not quite conforming). Do note that you _almost certainly_ want to use `std::vector` because the fact that it has 3 pointers doesn't matter because you _never_ pass objects by bitwise copy in C++. You pass them by reference and that is a single pointer's worth of copy. – Aykhan Hagverdili Aug 28 '21 at 10:45
  • @AyxanHaqverdili Yes, that could be good. Thank you. – Marko Grdinić Aug 28 '21 at 11:15