#development
1 messages · Page 173 of 1
cmake_minimum_required(VERSION 3.26)
project(Vector)
set(CMAKE_CXX_STANDARD 20)
add_executable(Vector main.cpp
Vector.cpp
Vector.h)
even the cmake says its c++20
no i mean the cxx standard in the ide settings
Im pretty sure I set it to above c++ 17
sometimes it choses to not include certain headers if language standard is set to older ones
where is it at in clion
settings -> build / exec / deploy iirc
or just type c++ at the search bar
look for anything mentions language level
Try running clang++ -std=c++20 -O3 Vector.cpp main.cpp in the command-line and see if that works
waiting for clang#
PS C:\Dev\Vector> clang++ -std=c++20 -O3 Vector.cpp main.cpp
In file included from main.cpp:2:
./Vector.h:19:32: error: no template named 'optional' in namespace 'std'
19 | int* insert(int element, std::optional<int> index);
| ~~~~~^
1 error generated.
Hmm... are you sure you've saved the file after including the appropriate header?
since when do u use c#
since i can see
jokes aside, my dad does .net dev and he asks me with his stuffs sometimes
damn
Your error occurs on line 19 but the code you shared has that code at line 25
do u use c#
Yep
thats nice
which is why I am even more confused
Try manually saving once
even main.cpp doesn't have 19 lines
maybe just start a new project, just a suggestion

Still does nothin
might just give up ngl 
even c++ dont want me to succeed
did you change language level in settings
@sharp geyser maybe its time for u to go to bed 
Wait
The error occurs in your header file, not source file
Show that
do you need to do #include <optional> in header files?
Yes


No one told me this
😭
Well now its giving issues
saying that insert expects 2 arguments

I thought to whole point of using std::optional was to let it know that it isn't required
Show the error
lmao
you imported the lib?
now turn off ur laptop
C:/Dev/Vector/main.cpp:9:16: error: too few arguments to function call, expected 2, have 1
9 | vec.insert(100);
| ~~~~~~~~~~ ^
C:/Dev/Vector/Vector.h:20:7: note: 'insert' declared here
20 | int* insert(int element, std::optional<int> index);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
but isn't the whole point of using std::optional to define it as an optional argument?
std::optional does not behave like JavaScript's definition of "optional"
Assign the second parameter a default value of std::nullopt
cause I don't always want to have to supply index unless I am wanting to set a specific index
though i recommend doing something like this @sharp geyser
its much cleaner than using std::optional for the second argument
Not really because it duplicates implementation
Doing that requires you to provide the function body multiple times
yea I dont understannd nullopt from that reference thing so ima just say fuck it and just supply an index

right?
int foo(int bar) {
// Some 50 lines of code
}
int foo(int bar, int baz) {
// Same 50 lines of code with adjustments to use `baz`
}
// Meanwhile
int foo(int bar) {
foo(bar, std::nullopt);
}
int foo(int bar, std::optional<int> baz) {
// 50 lines of code, adjusting based on value existence (`std::optional::has_value()`)
}
Doing this if you go out of bounds it just returns 0 no?
at least according to my tests

dk if that expected behavior
hmmmmm
Also is there a need to differentiate between length and capacity?
{} is a zero-initializer, in case of std::optional, it's zero-initialized to std::nullopt
could I not just use capacity to determine my length?
Yes
What?
you cant
there's a difference between the array's capacity in memory and the amount of populated elements (length)
the array's capacity after initialization is always > 0, while its length can be zero
uh oh spaghettio
Capacity is just a integer telling you when to extend the internal array when the length reaches the capacity
The reason you need to declare a length field/property yourself is because you're using a pointer to store the values which does not have size information as I showed before
So wait
but capcity seems to always be equal to length in my implementation
which was why I was wondering
seemed like a wasted variable
Can you show your current implementation?
i'm thinking like this
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
for my impl, the capacity doubles the size of size
I wasn't sure if I should double it
or just add +1 for each element that is added
though
so it is always equal to the amount of items in the vector
you will need to allocate a new array everytime an element exceeds capacity
since array is constant-size
also what is auto
basically type inferring
"infer the type from this expression"
The length is supposed to start from 0, and should be incremented every time data is pushed to the array
right
bru why not use realloc
its cleaner than new, then delete
The capacity should start from 1, and be increased by power of 2 every time the length reaches the capacity
or does that also not work? 
delete
so basically a towers of hanoi but without moving pieces around
it's simple then, just sort the values descending
irght now it is almost correct almost.
Instead of 6 it returns me 5 for one test case..
pointers only point
they have no value by themselves
But still i have no clue what's wrong with my algo. Something small is off.
it returns it to the operating system
Basically
void push(T value) {
if (current == capacity) {
T* tmp = new T[capacity * 2];
// Move elements from previous array to the new one
capacity *= 2;
delete[] arr;
arr = tmp;
}
arr[++current] = value;
}
does
T new_array[capacity * 2]{};
also work for constructing new array
wtf is T
The type your vector holds
if you free a pointer it should the same pointer (not modified with pointer arithmetic) as the one you initialized with new/malloc
I don't even know how to use generics yet
he he he ha
so for now ima stick with ints
that's not possible unless you use new, no?
sort all values descending, then simply iterate once
@earnest phoenix But I have a question, if length starts at 0, and capacity starts at 1, how is insert ever supposed to work.
as you already know that if i is smaller, i + N will be smaller too
Yes
It would never evaluate to true
THIS
Yes but like, how am I to ever increase the length if I can't insert anything into the vector
😭
so length == capacity will always be false
you can?
length will always be less than capacity
also would
delete old[];
``` works for deleting array
yes
😔
hollup can i send you my current algo?
I guess I am not making myself clear enough
sure
delete[] value; not delete value[];
So length starts out at 0, capacity at 1. insert is my method for adding things to the vector. Vector is initalized with nothing in it. So how do I add stuff to it, if its length is 0, but its capacity is 1
length == capacity will always be false in this case
what is the difference?
delete value[] is a syntax error
wait how come my ide doesn't tell me anything
The value being added is done outside of the condition
the check is done before appending values
something like
void push(...) {
if (current == capacity) {
// Capacity reached, allocate new array with higher capacity and move elements of the previously allocated array to the new one
}
// Add element
}
i have sent you in the dm

why are yall using vector btw?
oh no, I mean chitty
oh
it must be dynamic
i have sent the test logs in your dm as well
owh yeah my teacher told me to use vectors tho
weird
I am 100% sure that my first part of createboxpartitions is correct
@earnest phoenix also how can i infer the length of this kind of constructor?
auto a = Vec<int>{1, 2, 3};
you cant
ok so, what's the final goal?
wait that is macro?
System.out.println("SEEECOOOONNDD PAAAARRTTTT");
for(int i = 0; i < boxPartitions.size(); i++){
Vector<Vector<Double>> currentBox = new Vector<>();
Vector<Vector<Double>> selectedBox = new Vector<>();
selectedBox = boxPartitions.remove(i);
currentBox.addAll(selectedBox);
for(int j = 0; j < boxPartitions.size(); j++){
if(i != j) {
if (isSmaller(selectedBox.get(0), boxPartitions.get(j).get(0))) {
currentBox.addAll(boxPartitions.get(j));
boxPartitions.remove(boxPartitions.get(j));
j = 0;
i = 0;
}
}
}
boxPartitions.add(currentBox);
}```
this part gotta be wrong
what macro?
it partitions all boxes together that fit in each other such that it returns the minimal amount of boxes.
then how?
then you're overengineering it
A box fit, if there exists a permutation such that all dimensions of the box are bigger than the other:
box1: [x, y, z], box2: [x, y, z]
then it can be that [y,z,x] fits in [x, z, y]
as x > y, z> z, z> y
gn
cya
also this
I mean i am really close now, i know where the problem occurs but i am unsure how to fix it.
this is 100% false for some reason
hm
wait is that actually possible for custom classes
some kind of operator fuckery or something
i know it's overengineering but at this moment i really can;t afford to change it all over again
if you don't understand the code i can explain it to you for sure
or is that only a compiler thing
sorry for the bad code btw, i didn't clean anyting or tried optimizing it until it works completely
i'm more towards C
Okay but before I go to sleep
i am just trying to get the right base set such that i can later on make it better
wait... what
vec.insert(0, 100);
vec.insert(1, 1000);
for(int i = 0; i < vec.length; i++) {
std::cout << vec[i] << std::endl;
}
0
100
1000
why this output that 
me when undefined behavior
doesn't insert take all elements to insert?
for some reason it prints 0 at the beginning of everything
its starting to bother me
we'll look at this tomorrow
@earnest phoenix WE OUT HERE 🗣️ 💯
copied sayu's way of copying elements from the old array to the new array
for(int i = 0; i < this->length; i++) {
std::cout << i << std::endl;
new_array[i] = this->array[i];
}
but it needed to be this->length - i
wym
wha
doing i < this->length for me caused problems
if you copy items from old array to new then would would you
so changing it to this->length - i helped
dafuq
stroke?
bru your code is broken
I know I keep saying ima sleep but I still want to recap on what I've done and make sure my head is in the right place
E
your head will be in the right place once you wake up
void Vector::insert(int index, int element) {
if(this->length == this->capacity) {
this->capacity *= 2;
std::realloc(this->array, this->capacity);
}
this->array[index] = element;
this->length += 1;
}
So from my understanding
- Checking to see if the length of the array has reached the capacity
- If it has realloc the array so it can handle a higher cap
- If the check is false just add an element and increment the length
you dont need to reassign with a for loop after realloc
the for loop after realloc is useless
Really?
I see
Actually you're right
idk what I was thinking
😔
I just need to expand the capacity if the length has reached the cap
no need to make a new array
Well damn
thats much shorter now

step 2. make an operating system
gn
have a nice dream about kernel segfaults
imagine having nightmares about segfaults
when you use 🚀Rust🚀

malformed unsafe code:
me when stdcore is unsafe
it cant be unsafe because its 🚀Rust🚀
Huh?
Real?
no 
oooooo C++ dev stuff
good ta
finally got my database layer refactored in my latest bot!
been meaning to do this since sporks, never had opportunity
now uses prepared statements, and caches the statment handles
so if you do the same query twice, it absolutely stonks
ive seen so many sql libs, and some dont even do prepared statements, those that do, they dont seem to remember the statement ids
so they will always re-prepare each time anyway, defeating the point
dealing with the underlying C library is pain incarnate
https://github.com/brainboxdotcc/beholder/blob/main/src/database.cpp#L255
Damn and here my biggest worry is implementing my own vector
You got it rough 
lol yeah
C libs and raw pointers suck ass
why are you implementing your own vector? whats wrong with std::vector?
you tried making a bot in C++ yet?
I installed it with vcpkg and then tried using it in my project but it couldn’t find it I guess
im hoping to finish off my bot soon... just need to finish dashboard and premium stuff
its not as complex as sporks or triviabot, but the code for both bot and dashboard was written from scratch, chucked away all my technical debt
as such its much nicer!
look how neat main is lol
https://github.com/brainboxdotcc/beholder/blob/main/src/main.cpp
Oh nice man, sounds like a fun project
its like 20 lines
Dayum you’re splitting off event handlers nice
I myself would of just did it all in the same file 
yeah its nice when its done neatly
I’m not very good at neat
Isn’t this considered a bad way to seed randomness
@wheat mesa https://github.com/Mistyerious/Vector this is my current progres if you are interested.
I didn't do much as I started it last night
can i do a pull request
If it improves the code while also explaining those improvements go for it
I don't want to just be left in the dark on what its doing as this is a learning experience for me
@sharp geyser @earnest phoenix https://github.com/Mistyerious/Vector/pull/1
im assuming it is only supposed to hold ints?
That is indeed its original purpose
as dealing with ints seemed easier than any and all types
Dont even know what templates are
i just added gif flattening to my bot, drove me nuts lol
basically if i just try and deal with a big animated gif, tesseract cant OCR it and the image recognition API tries to scan every frame and would cost me a ton
in some situations you do want to see every frame to see if someones "done a fight club" and hid pr0n in one frame, so you can yeet the image away
but in this case, no
@green kestrel can you review this pull request
i haven't used C++ in like 2 years lol
thanks null, I forgot to check if the index is out of bounds with the length of the array to begin with when inserting

also why size_t
It’s basically generics
looks ok to me
But a bit more powerful
im not sure about using std::realloc tho
Also wait isn't index >= length counterintuitive? Unless I am misinterpreting the result
std::realloc is for use with malloc and free NOT new/delete
shouldn't it be <=
It’s the pointer width unsigned size type which is 8 bytes on 64 bit systems and 4 bytes on 32 bit systems
iirc theres no "reallocate" for new
(Or if I’m wrong brain can correct me)
yes
size_t is the correct size to cover a 64 bit size on a 64 bit system or 32 bit size on a 32 bit system
It’s the same as usize in rust
should I use malloc over new?
size_t x{0};
x -= 1;
// x == 18446744073709551615
this can really bite you in the ass, if you accidentally decrement a loop counter below 0
C++ will not hold your hand, it wont throw, it'll just silently wrap
new is technically the way to do things in C++, but tbh it mostly comes down to preference
Does it not?
never use malloc!

Well I meant more or less for allocating memory blocks
similarly, this means its destructor is not called either if you free()
I suppose that’s a good point though
C didn’t have all that fun stuff so it makes sense that new and delete didn’t exist
So using realloc with new is not good?
placement new is where you can allocate your memory however you like, with malloc, with a magic spell from hogwarts, however, then you placement-new an object at a specific address and it calls its constructor
afaik for this case it’s probably fine since you’re not using templates and only supporting integers
its undefined behaviour, new is not aware of malloc's memory blocks and vice versa so realloc will give gibberish
you gotta use malloc, if you want to use realloc, but be aware it wont call constructors, or you can use new/delete and memcpy
i'd do new, memcpy the whole array to new location, and then delete[] old array
I see
im curious now how std::vector does it
SHIT I FORGOT A DESTRUCTOR 
as it certainly doesnt copy the whole thing on reallocation
ah it does!
Notes: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the size specified in the most recent call to reserve().
so if you go past the reseved vector size, all elements are reallocated and any held references to them are invalidated
if you stay within the reserved size, it wont reallocate
yes, which is why i used it
void Vector::insert(int index, int element) {
int *old = nullptr;
if(this->length == this->capacity) {
this->capacity *= 2;
memcpy(old, array, capacity);
delete[] array;
array = old;
}
this->array[index] = element;
this->length += 1;
}
So would something like this be correct? memcpy takes in a destination, source and a size. I set the dest to be a placeholder and then I set the source to be the current internal array and its capacity to be the new capacity. then I delete the old array and set it to be the new modified one.
yes something like this
btw
std::reallocate is allowed to do exactly this under the hood
so in that case you dont gain anything
Oh?
yup
wait is std::reallocate a thing
can someone help me in #topgg-api pls
So reallocate does exactly what I just did?
yes
realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned. If realloc() fails the original block is left untouched - it is not freed or moved.
yes, but while using malloc() not new[]
Something I’ve been confused about recently, how does delete[] know when to stop freeing memory? How does it know how much memory belongs to the pointer it is being used on? Is this something that is handled by the allocator via storing extra info about a specific address?
gotcha
if you do int a = new int[50] then when you do delete[] a it knows a is 50 ints
should i not use realloc
memory allocators keep record of allocations
I see
if you accidentally did delete a, its a memory leak at best, corrupted heap at worst
gotta remember not not mix up delete[] and plain delete
Wouldn’t this make memory leaks relatively “detectable”…?
can i get some help in #topgg-api please
not really
which has always irked me as like i said, it knows the size of what you allocated, i guess its to be sure it can call dtors of all elements in an array...
especially if your codebase is hella complex
if you want to detect memory leaks, use valgrind
Well, for smaller or more trivial leaks
Yeah I do, fantastic tool
getting used to valgrind and gdb is one of the best things you can do for your sanity in C++ land
So your code is unreachable btw

wdym
I merged the pull request, and then pulled the code to my workspace and it is all unreachable
inside the if index >= length block
bru i didnt tell u to merge it already
was that not what you said?
i wanted for Voltrex to review it first
brain is just as good as voltrex
Still kind of weird how the code is seemingly unreachable
he's been doing C++ longer than most of us have been alive
I wish I had more time to actually program things
I have a whopping one class that I actually write code in
hey null
hey misty
yes
^
====================[ Build | Vector | Debug ]==================================
"C:\Program Files\JetBrains\CLion 2023.2.2\bin\cmake\win\x64\bin\cmake.exe" --build C:\Dev\Vector\cmake-build-debug --target Vector -j 18
[1/3] Building CXX object CMakeFiles/Vector.dir/Vector.cpp.obj
[2/3] Building CXX object CMakeFiles/Vector.dir/main.cpp.obj
[3/3] Linking CXX executable Vector.exe
FAILED: Vector.exe
cmd.exe /C "cd . && C:\PROGRA~1\LLVM\bin\CLANG_~1.EXE -fuse-ld=lld-link -nostartfiles -nostdlib -O0 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -g -Xclang -gcodeview -Xlinker /subsystem:console CMakeFiles/Vector.dir/main.cpp.obj CMakeFiles/Vector.dir/Vector.cpp.obj -o Vector.exe -Xlinker /MANIFEST:EMBED -Xlinker /implib:Vector.lib -Xlinker /pdb:Vector.pdb -Xlinker /version:0.0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
lld-link: error: undefined symbol: public: __cdecl Vector<int>::Vector<int>(void)
>>> referenced by C:\Dev\Vector\main.cpp:6
>>> CMakeFiles/Vector.dir/main.cpp.obj:(main)
lld-link: error: undefined symbol: public: void __cdecl Vector<int>::insert(unsigned __int64, int)
>>> referenced by C:\Dev\Vector\main.cpp:8
>>> CMakeFiles/Vector.dir/main.cpp.obj:(main)
>>> referenced by C:\Dev\Vector\main.cpp:9
>>> CMakeFiles/Vector.dir/main.cpp.obj:(main)
lld-link: error: undefined symbol: public: int & __cdecl Vector<int>::operator[](unsigned __int64) const
>>> referenced by C:\Dev\Vector\main.cpp:14
>>> CMakeFiles/Vector.dir/main.cpp.obj:(main)
lld-link: error: undefined symbol: public: __cdecl Vector<int>::~Vector<int>(void)
>>> referenced by C:\Dev\Vector\main.cpp:18
>>> CMakeFiles/Vector.dir/main.cpp.obj:(main)
>>> referenced by C:\Dev\Vector\main.cpp:18
>>> CMakeFiles/Vector.dir/main.cpp.obj:(?dtor$11@?0?main@4HA)
CLANG_~1: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Oh
can anypne help me pls?
Wait patiently my g
Separating templates between .h and .cpp files gets messy
when someoen can help they will
Idk why, brain can probably explain
its 12pm for me
Okay and
I just know I have a lot of issues doing that
at night
true
That doesn’t change anything
Someone will respond to you when they do
Just be patient
ok
cc @green kestrel
You asked your question 10 minutes ago and have been spamming for the last 5 minutes for someone to help, I would be surprised if someone even responded within the hour
i did this pull request a few minutes before i went for school so apologize if i fucked up 
i tested it on a single cpp file and it worked lmao
don't know why linking doesn't work
What exactly does that mean?
need inline on it, if it has no body and no presence in the cpp file, only the header
wdym?
all functions should be defined in the cpp file, no?
for templates, no
template functions/classes are generally inlined
this is the one with the pr where templates were added yes?
smh without brain/volt reviewing
like merge the function definitions in Vector.cpp with the class definition in Vector.h to Vector.h
but I will have to read into it
like
Vector.h:
template<typename T>
class Thing {
public:
void thing();
}
Vector.cpp:
template<typename T>
void Vector<T>::thing() { ... }
into (in Vector.h):
template<typename T>
class Thing {
public:
void thing() { ... }
}
and delete the Vector.cpp file
@sharp geyser

I see now
but I am not quite sure I understand why is there even the need of a cpp file if you can just do it all in the header file
when your project grows more advanced, your code needs to be split in several cpp files
and those cpp files can depend on each other
whether your library be done through only headers or done through linking is only a matter of preference tho
for some reason templates cant be done through linking (as Brain said) soooo
really?
So you are kind of forced to do it all in a header file if you are using templates
yes
that seems kinda bogus
yes, it's a destructor
it's for freeing/deleting things like pointers allocated with malloc/new
it's called implicitly for you whenever your object goes out of scope
Vector() : capacity(1), length(0), array(new int[1]) {};
explicit Vector(size_t size) : capacity(size), length(1), array(new int[size]) {};
so what exactly is this called?
I didn't know you could do Vector : prop()
yes, it also allows for polymorphism (like extends in JS)
@solemn latch fix automod 
I can't even post c++ error messages without it saying it is harmful
it thinks its a phone number 👀
bru
stop posting phone numbers 
lol
whats in Vector.h
//
// Created by dyeaaaronjr on 11/13/2023.
//
#ifndef VECTOR_VECTOR_H
#define VECTOR_VECTOR_H
#include <stdexcept>
template <typename T>
class Vector {
T *array;
size_t capacity;
size_t length;
public:
Vector() : capacity(1), length(0), array(new int[1]) {};
explicit Vector(size_t size) : capacity(size), length(1), array(new int[size]) {};
constexpr size_t size() { return length; }
inline void push_back(T element) { insert(length, element); }
void insert(size_t index, T element) {
if (index >= length) {
int* old = nullptr;
if (length >= capacity) {
capacity *= 2;
memcpy(old, array, capacity);
delete[] array;
array = old;
}
array[index] = element;
length = index + 1;
}
}
T &operator[](size_t index) const {
if (index >= length) {
throw std::range_error("index out of range");
}
return array[index];
}
~Vector() {
delete[] array;
}
};
#endif // VECTOR_VECTOR_H
Basically just what you told me to do, which is merge cpp to .h
why did u change insert
bru okay
I wish the debugger told me more
change int* old with T* old and memcpy(old, array, capacity); with memcpy(old, array, capacity * sizeof(T));
I see
also put array[index] = element; after the if statement
Okay
and the capacity *= 2; should be in a while loop like the one i did in my pr
okay that's enough suggestions

Why in a while loop?
like what if someone does
vec.insert(0, 200);
vec.insert(4, 600);
vec.insert(9836362, 900);
afaik there's a mathematical way to do ```cpp
while (capacity < length) {
capacity *= 2;
}
One message removed from a suspended account.
Also
One message removed from a suspended account.
because i have to
One message removed from a suspended account.
None of this really fixes the obscure error of (0xC0000005) 😭
Why are C++ errors so obscure
If it was better I might be able to fix it myself
@sharp geyser what's in Vector.h now
//
// Created by dyeaaaronjr on 11/13/2023.
//
#ifndef VECTOR_VECTOR_H
#define VECTOR_VECTOR_H
#include <stdexcept>
template <typename T>
class Vector {
T *array;
size_t capacity;
size_t length;
public:
Vector() : capacity(1), length(0), array(new int[1]) {};
explicit Vector(size_t size) : capacity(size), length(1), array(new int[size]) {};
constexpr size_t size() { return length; }
inline void push_back(T element) { insert(length, element); }
void insert(size_t index, T element) {
if (index >= length) {
T* old = nullptr;
if (length >= capacity) {
while(capacity < length) {
capacity *= 2;
}
memcpy(old, array, capacity * sizeof(T));
delete[] array;
array = old;
}
length = index + 1;
}
array[index] = element;
}
T &operator[](size_t index) const {
if (index >= length) {
throw std::range_error("index out of range");
}
return array[index];
}
~Vector() {
delete[] array;
}
};
#endif // VECTOR_VECTOR_H
now implement remove and suffer with shifting :tf:
First I have to fix my current problem
😔
um remove the T* old = nullptr; and add T* old = new T[capacity]; the line before memcpy
Isn't that just making a new array of that type with the capacity ?
damn IDE
a null pointer must NOT be modified/dereferenced
bruuuuuhhhh
maybe this is what happens when u mix new with memcpy
idk @green kestrel

according to brain its better to use memcpy when using new/delete
Unless I misunderstood him
look i rarely use new/delete, i'm more used to malloc/free 
I am used to neither
also doesn't help that it could literally mean a number of things
I am either freeing memory that is already freed, writing into memory that is unallocated or attempting to access elements in the memory that has already been freed according to stackoverflow
memcpy doesn't do any allocations, it doesn't matter
memcpy simply reads the amount of bytes from one buffer and copies it into the other
^
I see
the fact is that you're doing T* old = nullptr which means old is not allocated
you're then attempting to copy into memory that you don't own
so it requires me to already have an allocated array in memory for it to copy to
yes
you need to allocate space in old in order to use memcpy on it
thats why i told u to use T* old = new T[capacity];
show the current snippet
and yet its causing a heap corruption
void insert(size_t index, T element) {
if (index >= length) {
if (length >= capacity) {
while(capacity < length) {
capacity *= 2;
}
T* old = new T[capacity];
memcpy(old, array, capacity * sizeof(T));
delete[] array;
array = old;
}
length = index + 1;
}
array[index] = element;
}
onto your next problem
old and array have different sizes
you're attempting to copy capacity * sizeof(T) bytes from array to old
it's reading past what array owns
wait really?
don't use memcpy here
isnt array the same size
why would it be?
this logic assumes that the length is greater than the capacity and therefore you must grow the array
yes
therefore array has a smaller size than capacity * sizeof(T) after you modify it
int oldCapacity = capacity;
while(capacity < length) {
capacity *= 2;
}
T* temp = new T[capacity];
for (int i = 0; i < oldCapacity; i++) {
temp[i] = array[i];
}
delete[] array;
array = temp;
try something more like that
oooooooo
I swear I was doing that before like way earlier
i forgor sorry
not the for loop, tho
yes the for loop
you can still use memcpy here
you can but I figured that memcpy would be a little more convoluted for understanding here
you just have to memcpy the amount of bytes that array actually owns, nothing more
so instead of capacity * sizeof(T) would it not just be oldCapacity?
int oldCapacity = capacity;
while(capacity < length) {
capacity *= 2;
}
T* temp = new T[capacity];
memcpy(temp, array, sizeof(T) * oldCapacity);
delete[] array;
array = temp;
this would work
size_t new_capacity = capacity;
while (length > new_capacity) {
new_capacity *= 2;
}
// ...
T* old = new T[new_capacity];
memcpy(old, array, capacity * sizeof(T);
capacity = new_capacity;
sorry forgot that capacity changes
this actually
the reason you need sizeof(T) here is because memcpy copies the exact amount of bytes, not elements, that you give it
^
isnt it new T[oldCapacity]; because otherwise the array doesnt grow at all
or wait
nvm
lemme see what you're running
both in your main.cpp and in the snippet
#include <iostream>
#include "Vector.h"
int main() {
Vector<int> vec;
vec.insert(0, 100);
vec.insert(1, 1000);
// vec.push_back(10000);
std::cout << vec.size() << std::endl;
for (int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
return 0;
}
void insert(size_t index, T element) {
if (index >= length) {
if (length >= capacity) {
int oldCapacity = capacity;
while(capacity < length) {
capacity *= 2;
}
T* old = new T[capacity];
// memcpy(old, array, oldCapacity * sizeof(T));
for (int i = 0; i < oldCapacity; i++) {
old[i] = array[i];
}
delete[] array;
array = old;
}
length = index + 1;
}
array[index] = element;
}
oh I see why this is unreachable
how would length ever be greater than capacity?
(if you're not incrementing it before you do the check?)
See that's what I thought, but I also wasn't too sure
void insert(size_t index, T element) {
if (index >= length) {
if (index >= capacity) {
// grow the array
}
length = index + 1;
}
array[index] = element;
}
something more like that
the reason you're getting a memory corruption is because the array is never even growing with this logic
and then it assigns to memory that isn't allocated/it doesn't own
(the OS really dislikes that)
try it
if the index is greater than the length but within the allocated capacity of the array, you can just shove it into the array without needing to reallocate
if the index is greater than the capacity, then you need to reallocate to fit it
Yea it still causes a heap corruption and then its not allowed to even go past the size of the initial array
yeah
lemme see exactly what you're writing
void insert(size_t index, T element) {
if (index >= length) {
if (index >= capacity) {
int oldCapacity = capacity;
while (capacity < length) {
capacity *= 2;
}
T *old = new T[capacity];
// memcpy(old, array, oldCapacity * sizeof(T));
for (int i = 0; i < oldCapacity; i++) {
old[i] = array[i];
}
delete[] array;
array = old;
} else {
length = index + 1;
}
}
array[index] = element;
}
Am I still not understanding what you're saying?
get rid of the else
just put the length = index + 1; outside of the else but within the first if
because either way your length should be the last element index + 1
Okay so still heap corruption but it adds the elements appropriately
wdym heap corruption still
I still get a error that a heap corruption occured
does it happen before or after the elements get inserted
Seems to be after
because if it happens after then your insert function is fine
something else is wrong
T &operator[](size_t index) const {
if (index >= length) {
throw std::range_error("index out of range");
}
return array[index];
}
likely this then
or something related to it
this looks fine
Idk what else it could be then
cause I am only using .insert
and then looping over my newly created vec
Vector<int> vec;
vec.insert(0, 100);
vec.insert(1, 1000);
// vec.push_back(10000);
std::cout << vec.size() << std::endl;
for (int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
main.cpp
what about the size function
I make a vector, insert into it, then loop over it
size just returns length
constexpr size_t size() { return length; }
so that it's evaluated at compile-time?
ask null, I forgot to ask about that specific thing
but size isn't a compile time thing
isn't it runtime?
but it compiles though
length is not constexpr, how can that function return a constexpr
that doesn't make sense
it's like a const function in Rust
like when you do a len function in rust you tend to do this:
const fn len(&self) -> usize {
self.len
}
this does not make sense
mark the function as const, don't mark it as constexpr
I have no idea why that even works
I don't know, but it doesn't feel right
Will that even fix the heap corruption issue
no
the function does not change at all
how would that even make sense
I was about to say
to be constexpr
the length completely depends on runtime info
btw I figured out what's wrong
you're never incrementing length
lol
for (int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
I have a feeling the issue occurs here.
see smh
in your insert function
you're only changing length if the array resizes
which doesn't always happen
which would make sense because then length is always 0 here
what if someone do this tho ```cpp
vec.insert(5, 3);
vec.insert(1, 2);
That got removed when I pulled the pr
that's already handled
So after array[index] = element; should I do length += 1;
yes
void insert(size_t index, T element) {
if (index >= length) {
if (index >= capacity) {
// grow the array
}
length = index + 1;
} else {
length++
}
array[index] = element;
}
or length++;
no
well
I guess you could
you'd just have to change the length = index + 1 to length = index
this logic should work
haven't tested it tho
to continue on, there is still a heap corruption somewhere
can you push to your repo so I can look at the full thing
Yep
bet
top 10 last words
real
there
you good if I make a PR to this?
is that else should be there tho
like if the index is lower than length, the length still grows
I welcome it
@wheat mesa
you can reformat it if you wish, my formatter is a bit different from yours
So wait
what was I doing differently than what you have
I dont see much differences
the nested if statements were probably messing with the logic
Ah
it was a bit difficult to read, so this is simplified to be much easier to understand
don't be afraid to separate things into private methods, especially resizing behavior like this
helps the logical flow a lot
you're boosting my resume rn 😎
hey man
Idm helping out a friend
Also
are things private by default?
I notice you didn't use private:
yes
interesting
private: is useless lmao
it's more for readability than anything
struct members default to public, class members default to private
unless you define a struct, which is public by default afaik
interesting
now to implement remove

should be simple
all I have to do is remove the element at a specific index and then shift all the elements up 1 I think
Waffle have you read my message
So when removing something from the array, should I worry about modifying its capacity or should I just keep it at its current capacity
@sharp geyser try removing that } else { length++; }
I fixed it in a pr
I think I am now ready to tackle machine learning
/s
smhhhh
Well all i am happy is that it works now
despite me requiring your guys help a lot
😔
did you remove it
it will break if you try to add in a reverse order unfortunately
yea
there you go
you didn't initialize the memory
vec.insert(0, 100);
vec.insert(4, 1000);
vec.insert(2, 1005);
vec.push_back(10000);
I also did this
you need to fix the ctor
Wanted to see what would happen
elements at index 1 and 3 are uninitialized
it's doing what it's meant to do but the memory is just garbage before you allocate it
so they are random blobs of RAM
actually now that I think about it shouldn't it be not doing that?
since you're allocating with new?
I think the issue is I am telling it to insert something at index 4 when 1 and 3 are basically nothing
Honestly does it matter if that happens?
some libraries/languages do this
Because then the entire block is 0s even though the user may be expecting a different behavior
Yes
Because new will invoke the parameterless constructor of T
I am talking about it just putting random junk in the place of index 1 and 3
ooo smh
And if you overwrite everything with 0 after that, you'd be potentially messing with data that was set by the default constructor of T
Does it matter if index 1 and 3 are just filled with junk data
Yes it does
hm
I think most people would be expecting it to be filled with zeroes for the case of integers
fair enough
then in that case ```cpp
if (index >= length) {
throw std::range_error("out of range");
}
this is going to look very cursed but just try it...
So should I just fill it with 0s to begin with and then whenever they insert it changes the value at that index
in your constructor change array(new int[1]) to array(new int[1]()) and do the same when resizing
or sorry not new int
new T
is what I meant
what does the parentheses do
Im not quite sure what they do either
that's nice
I see
it's only good if T is not a struct/class with a constructor, no?
That is nice
well, if T has a parameterless ctor then it's fine
oh okay
remove should be easy
all it is just removing at an index and then shifting the array elements up 1 to take the spot of the removed no?
time to look at what memset is
memset just sets a block of n bytes to whatever value you tell it to
it's basically a glorified for loop + assignment
memset(pointer_to_array_of_10_ints, 0, sizeof(int) * 10) will set an array of 10 ints to 0
I see
(in the byte level, NOT in the int level)
^^
why use memcpy here?
memcpy(&array[index_to_remove], &array[index_to_remove + 1], (length - index_to_remove + 1) * sizeof(T));
try something like this
i hope this is right
hm
so from my understanding
the destination is a reference of the array at that index, then the source is the reference at the index + 1, and then we are changing the size to be the length - index_to_remove + 1
why is it + 1 for the source?
because we want to move all elements after the index into the current index?
If you are able to explain it better than I please do
cause I am not sure I follow the entirety of it
@wheat mesa can u explain this
How does that accomplish this tho?
it copies the entire memory after the index into said index
ok so basically arrays are a continuous block of memory
and then you just length--;
Perdón we pero a mi me lo mandaron. Lamento tener que enviarte esto, pero ahora que lo has abierto no puedes dejar de leerlo. Hola, mi nombre es Teresa Fidlago. Mori 27 años. Si no envías esto a 20 personas, dormiré a tu lado para siempre. Si no me crees, búscame. Teresa Fidlago. Entonces envíe esto a 20 personas. Una niña ignoró esto y su madre murió 20 días después. NO ENVIE ATRÁS!!!. Lo siento, tuve que enviar esto. Por cierto, esto no es falso buscarla en google. Alguien me envió esto y tuve que hacer lo mismo, no me arriesgo a ignorar este mensaje, dime por qué esto sigue sucediendo, otra abuela leyó esto y se lo envió a 20 personas, pero el Internet se fue cuando se lo habia mandado a 19. Fue encontrada cortada en 5 piezas después de 1 día. Asegúrate de enviarlo.
this guy explains it better than i do
the first argument is saying that you want to copy into the location of the element you want to remove
array[index_to_remove] being the value of the item, &array[index_to_remove] being where that value lives at
and you're copying from the next element onwards
the first argument is the destination, the second argument is the source being the starting block of memory to copy from, and the third argument is the amount of bytes to copy
for (length - index_to_remove + 1) * sizeof(T) bytes
So basically
I am telling it to just copy the array of the next element after the one being removed to the destination of the removed
yes
so it kind of cancels each other out removing the element but leaving behind everything else?
Okay so it removes the element thats nice
but I am running into a heap corruption, which is probably because I am not doing any checks so that is to be expected
at least I can confirm it works beyond that, didn't know memcpy could be used like that
did u add length--; after memcpy?
yea
and checks whether index_to_remove is not 0 and less than the length
but what if they want to remove the element at index 0
well the same applies
are arrays in c++ not 0 based?
they are zero based
bout to say

well now u know
But yea
hm
Also
I just realized
I have been coding for hours straight
I haven't done that in a while

Okay man
why the fuck is there a heap corruption
I hate C++ right now



