So I tried to make a custom string & vector class (from a youtube channel named The Cherno). But when I tried to make a copy constructor on that vector class with my custom string class, I get this exception: str was nullptr (Occured in the string copy constructor) and also when I tried with a primitive data types (int) I also get this exception: std::move<int & __ptr64>(...) returned nullptr (Occured on the re_allocate function).
main.cpp:
int main() {
utils::list<int> list;
list.place(5);
utils::list<int> other = list; // Works fine if I remove this line
}
String copy constructor:
utils::string::string(const string& other)
: pr_Length(other.pr_Length)
{
// If the other string was not initialized then return
if (!other.pr_Init) {
pr_Init = false;
return;
}
// Allocates a new char*
pr_Data = new char[pr_Length + 1];
// Copy all the char* on other string and copy it here
std::memcpy(pr_Data, other.pr_Data, pr_Length + 1);
// This string is initialized
pr_Init = true;
}
Vector class:
template<typename T>
class list {
private:
T* pr_Array;
size_t pr_Size;
size_t pr_Cap;
public:
using ValType = T;
using Iterator = list_iterator<list<T>>;
list() {
re_allocate(2);
}
~list() {
destroy_all();
::operator delete(pr_Array, pr_Cap * sizeof(T));
}
list(const list& other)
: pr_Size(other.pr_Size), pr_Cap(other.pr_Cap)
{
re_allocate(pr_Cap);
}
void add(const T& elem) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::move(elem));
pr_Size++;
}
void add(T&& elem) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::move(elem));
pr_Size++;
}
template<typename...Args>
T& place(Args&&... args) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::forward<Args>(args)...);
return pr_Array[pr_Size++];
}
void destroy_back() {
if (pr_Size == 0) {
return;
}
pr_Array[pr_Size].~T();
pr_Size--;
}
void destroy_all() {
for (size_t i = 0; i < pr_Size; i++) {
pr_Array[i].~T();
}
pr_Size = 0;
}
const T& operator[](size_t i) const {
return pr_Array[i];
}
T& operator[](size_t i) {
return pr_Array[i];
}
const size_t size() const {
return pr_Size;
}
size_t size() {
return pr_Size;
}
Iterator begin() {
return Iterator(pr_Array);
}
Iterator end() {
return Iterator(pr_Array + pr_Size);
}
private:
void re_allocate(size_t cap) {
T* newBlock = (T*)::operator new(cap * sizeof(T));
if (cap < pr_Size) {
pr_Size = cap;
}
for (size_t i = 0; i < pr_Size; i++) {
new(newBlock + i) T(std::move(pr_Array[i]));
}
for (size_t i = 0; i < pr_Size; i++) {
pr_Array[i].~T();
}
::operator delete(pr_Array, pr_Cap * sizeof(T));
pr_Array = newBlock;
pr_Cap = cap;
}
};