Dynamic c++ array

I need to use dynamic memory to store a sequence of integers which supports random access (the sequence is inside a class/struct).
I can't use std::vector on this project.

Should I simply use a raw pointer and new/delete, or should I use std:: unique_ptr?

Opinions?

Attached: c-plus-plus-logo.png (1600x1600, 61K)

Other urls found in this thread:

lkml.org/lkml/2018/3/7/621
en.cppreference.com/w/cpp/language/copy_elision)
twitter.com/NSFWRedditVideo

>I can't use std::vector on this project.
Then you reimplement your own vector class

Why can't you use a vector? It's literally made for what you want to do.

>I can't use std::vector on this project.
why
>Should I simply use a raw pointer and new/delete, or should I use std:: unique_ptr?
hold up, what are you doing

Use std::boost::__cxx26::dynamic_integer_array

Forgot to mention it's supposed to act as 2d matrix, mb.

I can't use a vector because adding a single element:
1. checks if size > capacity, which it isn't because I would have reserved it to fit perfectly
2. increments the vector's size, which I don't need because because I'm storing the dimensions separately (height and width)
3. Unecessarily bloats the binary with shit I don't need (I'm only interating and subscript assigning)

Oh, and the dimensions are fixed (const), but are only known at runtime.

>Oh, and the dimensions are fixed (const), but are only known at runtime.
So they aren't fixed?
For fucks sake just allocate in constructor and deallocate in destructor. Easy as that.

> auto* arr = new std::array();
and
> int num_elements = 0;
easypeasy

That's called an array
you know what a vector is but you don't know what an array is?

>Easy as that.
And follow the rule of 5 because c++ makes everything unnecessarily complicated.

niggers

The size isn't known at compile time, so it's not an (std)array.
However, the size is fixed/const, as in it doesn't change throughout the rest of the program.

I'm considering using smart pointers because of this
mess

it's hard to know what's zero cost abstraction and what isn't and what are the costs of shit in 2019 because of all the CPU and compiler magic

anyway, is anyone teaching this shit?

The transgender at mozilla

dude thats just a dynamically allocated array
christ, this is why people should start with C

C had something called a Variable Length Array, where the size can be known at run time, i thought sepples had a similar feature

You should use a vector because it's simple, clear, concise, idiomatic and maintainable. Why are you prematurely optimizing?

This was originally done in C with malloc and free, I'm porting it to C++

VLAs are trash and a mistake

See

>VLAs are trash and a mistake
Do elaborate why, my negro friend

>I can't use std::vector on this project.
Yes you can

>3. Unecessarily bloats the binary with shit I don't need (I'm only interating and subscript assigning)
Learn C++ first and come back, retard.

>sizeof becomes a runtime operator
>stack overflows
>"on the heap or on the stack?" "yes"
>lkml.org/lkml/2018/3/7/621

it got so fucking bad they were made optional in c11 and don't even exist in c++

Just use fucking malloc.

Definitely unique_ptr, you're looking at zero cost, not just zero overhead. At reallocation, just 'move' a new array.
Make your own templated class and remember what a vector needs:
contiguous series of Ts
O(1) get_at(idx), O(N) find(value), O(1) amortised insert(value), O(N) remove(idx).
Always allocate more than you use. I recommend logarithmic growth (find a steep log value so you don't destroy your heap). Keep m_alloc_cnt and m_used_cnt.
If you really want to show off to the teacher for bonus points, specialise basic types (char, int, ...) to use 10-30 elements in the stack instead of slowly allocating to heap. I mean literally
T m_stack_arr[64 / sizeof(T)];
So you fit a single cache line. Or something similar, show off buzzwords. Then just need a boolean flag whether you're still in stack or gone to the heap. Again you can optimise that info in a bit field somewhere.
This will definitely win bonus points.
Good luck.

No, I can't

I've compared file sizes and generated asm
you do know monomorphism does increase binary sizes... right user?

>I can't use a vector because
>proceeds to list three things that aren't reasons he can't use a vector
Fuck off retard

int* array = new int[n];

C++ users don't even know their own language

Sounds like you ought to optimise your standard library for your use case instead of writing your own buggy mess.

That's not an array, that's a pointer to an int. Please don't write confusing and ambiguous code.

t. ard

typedef int* IntArray;

there. now you can communicate that it is an array.

Okay, however the standard says arrays can't be of size 0. And they can't be nullpointers, either. They also have a very fixed and known size so you can iterate over them without bounds errors. Congratulations, you have caused at least three bugs and UBs.

>sizeof becomes a runtime operator
well, you said you don't know the size of your matrix until runtime, right? so this isn't bad. in fact its the best you can do. in fact, sizeof becoming a runtime operator for VLAs is a completely BS complaint. Just use dynamically allocated arrays or neck yourself.

>"How do I create a 2d array in sepples"?
>Huge spergout from sepples users with no actual answer provided
Your language was a huge fucking mistake. Just malloc that fucking garbage.

so then define a matrix class that provides iterators, retard. internally it can store a pointer to a dynamically allocated array. I'm not even a C++ programmer, I took a semester in college.

You have to know the size of an array at compile time in C++? what kind of shitty language is that?

Banned in all serious projects because they're slow and easy to UB.

is all heap-allocated memory banned in "serious projects"?

That's not what you recommended.
There are several answers - one very detailed. malloc is pretty slow you're looking at several hundred lines of code in some libraries.

Just use a vector and use reserve before adding the elements. No rellocation occurs if you don't exceed the reserved size

I wasn't talking about how VLAs aren't appropriate in the op's context, I was criticising them in general

go back to webdev

Allocating no but deleting is in some RTOS. Explicit heap >> VLA trash.

Never devved a web in my life, I guess I'm just blessed to use a language where arrays can be declared at runtime, I never knew how lucky I was

>That's not what you recommended.
Are you just shitposting or do you want your problem to be actually solved? here you go retard:
class Matrix {
int* array;

public:
Matrix(int n) {
array = new int[n];
}

~Matrix() {
delete array;
}
};

int main(void) {
Matrix matrix = Matrix(8);
return 0;
}

Now you can fill in indexing and iterating.

Yeah I know, but it's still branching on
if (size() > capacity())

which just adds unecessary overhead

wow literally one instruction you fucking tryhard

also before you mention its unsafe because it only stores a pointer

add a member that stores the width and height, change constructor to take width and height and construct backing array with int[width*height]. then at runtime make sure that all attempts to index it are within range

Great I love this array it's so cool 8th grader could write it.

>There are several answers
People suggest things and other people sperg out about them?

>malloc is pretty slow
Evidence??

>you're looking at several hundred lines of code in some libraries.
And?

>then at runtime make sure that all attempts to index it are within range
Isn't that incredibly slow?
Having to branch each time you access and array sound like an awful idea.

>Evidence??
Benchmark it yourself on the standard library you use.
>And?
You could not use malloc and use/overload free or your own allocator.

Is C++ the only language that sparks a 50 post heated debate about how to use a 2D array?

new operator should be just as slow as malloc, shouldn't it?

when people say array, they mean std::array, aka stack array, which means the size must be known at compile time (discarding vlas)

otherwise, if the size can't be resolved at compile time, or if it's too big for the stack, you can create an array on the heap (new/malloc/STL/etc)

It's literally one single ALU instruction.
There are exactly two ways to make a 2D array in C++, vector or array. Period.
In the olden days when new wrapped malloc, yes. Nowadays, no.

you want arrays with size determined at runtime, you have to validate your indices at runtime. you can provided unchecked methods that don't check each access in situations you are sure your index is in range, but if I suggested that you'd complain about UB again

*at least one

Likely to be one, and very likely to take advantage of branch prediction so you can stop being a smartass and complaining about muh branches

>It's literally one single ALU instruction
Maybe, but you are still branching. Which in the worst case means your entire pipe gets flushed with can be dozens of CPU cycles worth.

still incrementing the vector's size :^)

you reserve the space

>you want arrays with size determined at runtime, you have to validate your indices at runtime
Nope.

>but if I suggested that you'd complain about UB again
Certainly not me.

This. There is no 'branch prediction' in C++. CPUs don't let you interface them at all. It's literally a black box optimisation, you write correct and terse code, and the CPU does optimisations for free. Don't try workarounds and hacks and other shenanigans, you don't know how the predictor works and can't touch it. Nobody here understands the statistics, polylinear optimisation, and numerical analysis required to properly interface a branch predictor so don't fucking do it.

>Benchmark it yourself on the standard library you use.
Certainly someone has already done so.
But I wouldn't even know what to compare it against...

>You could not use malloc and use/overload free or your own allocator.
Yes. You CAN do a lot of things.

yes

that doesn't prevent it
the size is always incremented
size = initialized elements
capacity = maximum amount of elements possible for the allocated storage

>Nope.
You have 2 minutes to write me the proof of concept of a runtime-determined array which does not go out of bounds, without checking for bounds.
>done so.
Invalidated by time. Do it yourself on your specific ISA.
>against
new.
>CAN
ok?

>>you want arrays with size determined at runtime, you have to validate your indices at runtime
>Nope.
Even for statically sized arrays, if you want to prevent UB you have to validate at runtime. This incorrect code compiles, even though it invokes UB.
int a = 10;
int array[10] = {0};
return array[a];

so either you allow UB or you validate at runtime.

>Nobody here understands the statistics, polylinear optimisation, and numerical analysis required to properly interface a branch predictor so don't fucking do it.
Too bad that doesn't stop people making up ghost stories about cache misses

So why can't OP use std::array? because then he couldn't keep shitposting?

>which does not go out of bounds
That's the obvious trade-off.

>Invalidated by time. Do it yourself on your specific ISA.
Too much effort. I don't care enough.

>You have 2 minutes to write me the proof of concept of a runtime-determined array which does not go out of bounds, without checking for bounds.
Just use Haskell, its powerful static typing system means you will never have a runtime error

>trade-off.
Not worth it. Don't write shitty buggy code retard.
>effort.
Goodbye.

>Don't write shitty buggy code retard.
What are you trying to tell me here?

>Goodbye
Bye!

The size isn't known at compile time

>tell me
Unless you prove your array is better than std::vector, it's not. Cause those people proved it fits the specs. Sit down and work. Or use std::vector

so then use

Yeah, we can tell

>Unless you prove
I asked you for evidence and you gave none.
What I take from that is that there is none.

pls explain whats wrong with the idea of implementing a matrix class that meets OPs goals. he can just copy std::vector basically, and remove element insertion/deletion

You do know that C++ doesn't generate what you don't use, right user?

std::unique_ptr is fine for your use case.

here you go OP, I'm sure you can write the rest
#include
#include

template
class RaiiVec {
public:
RaiiVec(std::size_t size)
: vec{ std::make_unique(size) } {}

private:
std::unique_ptr vec;
};

auto foo() -> void {
auto vec = RaiiVec(65536UL);
}

Absolute state of sepples """"developers""""

>none
I gave you the best evidence - verifiable, provable evidence. Not some random numbers someone put out somewhere. I can draw in ms paint if that's what you want.
>there is none
Logical fallacy.

>auto foo() -> void
>auto vec
____ yourself

fucking pajeets get out of my board

>"I don't know what this code does but I'll use it anyway"

I wrote it, you fucking retard.
What makes you think I don't know what it does?

oof and yikes, senpai

Let's read this together
>I don't know or care what this returns, called foo, takes no arguments, and returns nothing.
>I want a variable 'vec' and I don't know or care what type it is, that is identical to a 'RaiiVec' of 65536UL.
This is retarded, you're abusing language features for no reason. Here's the proper readable notation.
void foo()
{
RaiiVec vec {65536UL};
}

Oh and let's not forget you are implying RaiiVec is actually a size_t sometimes. You want
explicit RaiiVec(std::size_t size)

Also calling make_unique in C++17 has compilation and sometimes runtime overhead over implicit construction, the language can nwo properly deduce the templated argument itself.

*buffer = (int *)realloc(sizeof(int)*newsize);

>realloc
Why?

>I haven't written C++ since 98
trailling return types are a thing
auto foo() -> void
is exactly the same as
void foo()
only more consistent and legible (because of lambdas)

and
RaiiVec vec {65536UL};
is the same as
auto vec = RaiiVec(65536UL);

the standard mandates that the operator=() doesn't make any copy here

and by the way, your use of { } instead of () is ambiguous. { } is normally used when you are using aggregate initialization, e.g.
auto a = std::array { 1, 2, 3, 4, 5 };

note when specifing a size

it's just amazing how you managed to be wrong in every aspect

yeah, I forgot to add explicit

>calling make_unique in C++17 has compilation and sometimes runtime overhead over implicit construction
source? my understanding was copy elision would happen here, so calling make_unique or the constructor would be the same
what would you use instead?

>consistent
>legible
It's a workaround FOR lambdas.
>the same as
You are wasting compiler time and memory deducing the type for no good reason. And this sort of shitty syntax can easily break in the instance of
auto base_ptr = make_unique(/**/);

>operator=()
This is a copy constructor. By the way does your class have a default constructor?
>ambiguous
() is ambiguous due to C++'s undecided grammar. You could mean function declaration at some point.
>initialisation
It's your move to solve whether
vec{1} means vec of size 1 or vec with push_back'd 1 and how.

>copy elision
Depends on your compiler. Look up Sutter's CPPcons on back to basics c++ and such. I'd just initialise it on the spot.

>It's a workaround FOR lambdas.
if you use trailling return types for lambdas, using them for functions as well just makes you consistent

>You are wasting compiler time and memory deducing the type for no good reason
nigga are you serious?

>This is a copy constructor.
wrong. it's a copy assignment operator, which is optimized away too (see en.cppreference.com/w/cpp/language/copy_elision)

>() is ambiguous due to C++'s undecided grammar.
besides the point. you either use it or you don't

>It's your move to solve whether
vec{1} means vec of size 1 or vec with push_back'd 1 and how.
what?

well everything depends on the compiler, but if it's following the c++17 standard, copy elision must happen in that case

Reallocate a new amount of memory to your buffer, it doesn't flush the old memory data so if you're shrinking the buffer, you should be careful about truncated data in memory.