I'm writing a Vector class for my uni the task is to create a method that mutates the elements of this "vector" class into an object of the class itself and returns this object.
My problem is that as soon as I create the Object I should return it gets deleted from the heap.
I create a new Object from the class itself with new DynArray{} and push back the nonmutated elements into the Object. The problem is that before I even can use the Object (push the elements into the "Vector") it got deleted and is not present anymore. Therefore the program crashes. How can I avoid that from happening?
The mutation should take place in the method transform.
header file:
#ifndef DYNARRAY_H
#define DYNARRAY_H
#include <array>
#include <exception>
#include <iostream>
#include <functional>
class DynArray
{
public:
DynArray();
DynArray(int c);
DynArray(DynArray& copyArr);
~DynArray();
int& at(const int i);
int size();
int capacity();
void print();
void push_back(const int value);
void pop_back();
void erase(const int index);
void apply(std::function<void(int&)> f);
DynArray transform(std::function<int(int)> f);
void sort();
void sort(std::function<bool(int,int)> comp);
private:
int _capacity;
int _size;
int * arr = nullptr;
};
#endif // DYNARRAY_H
class file:
#include <dynarray.h>
DynArray::DynArray(){
DynArray(4);
}
DynArray::DynArray(int c) : _capacity{c+=c}, _size{0} {
arr = new int[_capacity];
}
DynArray::DynArray(DynArray& copyArr) : _capacity{copyArr.capacity()}, _size{copyArr.size()}{
arr = new int[_capacity];
for(int i = 0; i < copyArr.size(); i++)
arr[i] = copyArr.at(i);
}
DynArray::~DynArray(){
delete [] arr;
}
...
int& DynArray::at(const int i){
if( i >= 0 && i <= size() && size() > 0)
return arr[i];
else
throw std::invalid_argument("illegal Index");
}
int DynArray::size(){
return _size;
}
int DynArray::capacity(){
return _capacity;
}
...
void DynArray::push_back(const int value){
if(size() >=capacity()){
int * tmp = arr;
_capacity+=_capacity;
arr = new int[_capacity];
for(int i = 0; i < size(); i++){
arr[i] = tmp[i];
}
delete [] tmp;
tmp = nullptr;
arr[size()] = value;
_size++;
}else{
arr[size()] = value;
_size++;
}
}
void DynArray::pop_back(){
if(size() == 0)
throw std::runtime_error("Cant delete a non existing element");
else{
at(size()-1) = 0;
_size--;
}
}
void DynArray::erase(const int index){
if( index >= 0 && index < size() && size() > 0){
for(int i = index; i < (size()-1); i++){
arr[i] = arr[i+1];
}
_size--;
}else{
throw std::invalid_argument("illegal Index");}
}
...
DynArray DynArray::transform(std::function<int(int)> f){
DynArray * copyArr = new DynArray();
for(int i = 0; i < size()-1; i++)
copyArr->push_back(at(i));
for(int i = 0; i < copyArr->size()-1; i++)
f(copyArr->at(i));
return *copyArr;
}
main:
int main()
{
DynArray a(1);
a.push_back(1);
a.push_back(3);
a.push_back(44);
a.push_back(677);
a.push_back(23423);
a.push_back(312);
a.push_back(5645);
a.push_back(5645);
a.push_back(5213145);
a.push_back(561234785);
a.push_back(5675467);
a.print();
std::cout << std::endl;
a.pop_back();
a.pop_back();
a.print();
std::cout << std::endl;
a.erase(5);
a.erase(0);
a.print();
std::cout << std::endl;
DynArray bb;
bb = a.transform(addOne);
bb.print();
std::cout << std::endl;
}
Changed the default and copy constructor as suggested:
DynArray::DynArray() : _capacity{4}, _size{0}{}
...
DynArray::DynArray(const DynArray& copyArr) : _capacity{copyArr._capacity}, _size{copyArr._size}{
arr = new int[_capacity];
//createNewArray(_capacity);
for(int i = 0; i < _size; i++)
arr[i] = copyArr.arr[i];
}
Related
i have this reSize function in my Array header
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
and my main code:
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
the problem is after resizing, my values that were stored in "data" variable are gone.
when i commented the code.
//delete[] old
in the reSize function
it worked fine...so i guess the problem is when i delete the pointer it deletes also the pointer inside the struct object which i don't want it to happen..
i don't want to comment the command becuz a leak in the memory will happen...how to fix this problem ?.
Update: My Array Class .
#include <iostream>
using namespace std;
template <class T>
class Array {
private :
T* items;
int size;
int length;
public :
Array() {
this->size = 0;
items = new T[this->size];
length = 0;
}
Array(int size) {
this->size = size;
items = new T[this->size];
length = 0;
}
int getsize() {
return this->size;
}
template <class T> void push_back(T x) {
if ((length+1) <= size) {
items[length] = x;
length++;
}
else {
this->reSize(size+1);
items[length] = x;
length++;
}
}
template <class T> void Insert(int index, T x) {
if (length + 1 <= size) {
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[index] = x;
length++;
}
else {
this->reSize(size+1);
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[length] = x;
length++;
}
}
template <class T> int Find(T x) {
int index = -1;
for (int i = 0;i < length;i++) {
if (items[i] ==x) {
index = i;
break;
}
}
return index;
}
void remove(int index) {
items[index] = "";
if(index+1 < length)
for (int i = index;i < length-1;i++) {
items[i] = items[i + 1];
items[i + 1] = "";
}
length--;
}
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
void Merge(Array<T> x){
T* old = items; int oldlength = length;
items = new T[size + x.size];
size = size + x.size;
length += x.length;
for (int i = 0;i < length;i++) {
if(i< oldlength)
items[i] = old[i];
else
items[i] = x.items[i-oldlength];
}
delete[] old;
}
T& get(int index) {
return items[index];
}
}
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
// this line causes some problems
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
In your code, declaring Array<User> x(3) declares an empty array with 3 elements that are preallocated. The length property of the array is 0. When the array is copied, length(0) elements are copied over into the resized storage. When you access the 0th element, it won't be copied on resize. What you actually need to do is call push_back() to add an element to the array so that length becomes 1 and the element is copied on resize.
Also, your array class is lacking a proper copy constructor and move constructor, which means copying it won't work at all. This means that User cannot be copied properly since it contains an array, which means that resizing an array of User won't work. You need to implement a copy constructor and copy assignment operator to be able to copy the array. You also need a destructor since, right now, the array is leaking memory when it goes out of scope.
Everything seems to be copying fine, but when I call array2.print(), it shows segmentation fault. What am I doing wrong?
#include <iostream>
#include <initializer_list>
template <typename T>
class DynamicArray
{
private:
const int GROWTH_FACTOR = 2;
const int INITIAL_CAPACITY = 5;
T *m_array;
int m_capacity; // Capacity of the array
int m_size; // Number of added elements
public:
DynamicArray(std::initializer_list<T> elements)
: m_size(elements.size())
, m_capacity(elements.size() * 2)
{
m_array = new T[m_capacity];
std::copy(elements.begin(), elements.end(), m_array);
}
DynamicArray()
: m_size(0)
, m_capacity(INITIAL_CAPACITY)
{
m_array = new T[m_capacity];
}
~DynamicArray()
{
delete[] m_array;
}
DynamicArray(const DynamicArray& other)
: GROWTH_FACTOR(other.GROWTH_FACTOR)
, INITIAL_CAPACITY(other.INITIAL_CAPACITY)
, m_capacity(other.m_capacity)
, m_size(other.m_size)
{
T *m_array = new T[m_capacity];
std::copy(other.m_array, other.m_array + m_size, m_array);
}
int size()
{
return m_size;
}
int capacity()
{
return m_capacity;
}
void resize()
{
int new_capacity = m_capacity * GROWTH_FACTOR;
m_capacity = new_capacity;
T *temp = new T[new_capacity];
std::copy(m_array, m_array + m_capacity, temp);
delete[] m_array;
m_array = temp;
}
void deleteAt(int pos)
{
for (int i = pos; i < m_size - 1; i++)
{
(*this)[i] = (*this)[i + 1];
}
m_size--;
}
void insertAt(T value, int pos)
{
if (m_capacity == m_size)
{
resize();
}
for (int i = m_size - 1; i >= pos; i--)
{
(*this)[i + 1] = (*this)[i];
}
m_size++;
(*this)[pos] = value;
}
void append(T value)
{
insertAt(value, m_size);
}
void print() {
for (int i = 0; i < m_size; i++)
{
std::cout << (*this)[i] << ", ";
}
std::cout << std::endl;
}
T& operator[](int index)
{
if (index < 0 || index > m_size - 1)
{
throw std::invalid_argument("Index out of range!");
}
return m_array[index];
}
};
int main()
{
DynamicArray<int> array = { 1, 2, 3, 4 };
DynamicArray<int> array2 = array;
array2.print();
return 0;
}
The error is here
T *m_array = new T[m_capacity];
It should be
m_array = new T[m_capacity];
By declaring a new variable called m_array you hid the class member variable that you wanted to assign to. The technical name for this is shadowing, a good compiler would warn you about this.
You redeclare m_array in the cctor, which shadows the class member.
So I wrote this C++ Class for storing an Array:
#include<bits/stdc++.h>
using namespace std;
class Array
{
private:
int size;
int *A = new int[size];
int length;
public:
Array(int arr[],int sz = 10)
{
length = sz;
size = 10;
for(int i=0;i<length;i++)
A[i] = arr[i];
}
~Array()
{
delete []A;
}
void Display();
void Insert(int index, int x);
};
void Array::Display()
{//code}
void Array::Insert(int index, int x)
{//code}
int main()
{
int a[3] = {1,2,3};
Array arr(a, 3);
arr.Display();
arr.Insert(1,4);
arr.Display();
}
This works fine. But in the main() function:
int main()
{
int a[3] = {1,2,3};
Array arr(a, 3);
arr.Display();
}
I am passing the pointer to the array a in the Class constructor.
Is there a way to pass the array like this?
Array arr({1,2,3}, 3);
You probably need to use something like this. But please note this code is still not optimal and it is usually much better to use std::vector or in some cases std::array.
#include <initializer_list>
class Array
{
private:
int *m_data = nullptr;
int m_size = 0;
int m_capacity = 0;
public:
Array(int arr[], int sz = 10) {
m_size = sz;
m_capacity = sz;
m_data = new int[m_capacity];
for(int i=0; i < m_size; i++) {
m_data[i] = arr[i];
}
}
Array(const std::initializer_list<int> &il) {
m_size = il.size();
m_capacity = il.size();
m_data = new int[m_capacity];
auto it = il.begin();
for (int i = 0; i < m_size; ++i) {
m_data[i] = *it;
++it;
}
}
~Array() {
delete [] m_data;
}
int size() const { return m_size; }
bool empty() const { return m_size == 0; }
int& operator[](int id) { return m_data[id]; }
int operator[](int id) const { return m_data[id]; }
};
#include <cstdio> // for printf
int main() {
Array arr({1,2,3});
printf(" %i \n",arr.size());
return 0;
}
everyone!
I'm trying to do such task:
Create stack od strings, by writing several constructors, including copy constructor. All elements are hleds in an array. If an array have fixed size, in case of overloading, increase it. Create pop(), push() functions. Make a function, deleting every even element.
Got problem, after sizing of the stack
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstddef>
using namespace std;
class Stack
{
string *stck; //stack pointer
int sz; //stack size
int ts; //top of the stack
public:
//constructor
Stack(int size)
{
size=sz;
stck = new string[sz];
ts = -1;
};
//destructor
~Stack() {
delete []stck;
};
//copy constructor
Stack (const Stack &ob);
void Push(string itm);
string Pop();
void Show(int sz);
private:
void Resize(int sz);
};
void Stack::Push(string itm)
{
if (ts == sz)
{
cout<<"Stack is overflow"<<endl;
Resize(ts);
}
else stck[ts++] = itm;
}
string Stack::Pop()
{
if(ts<0)
{
cout<<"Stack is free"<<endl;
return 0;
}
else return stck[--ts];
}
void Stack::Show(int sz)
{
for (int i = 0; i < sz; i++)
{
std::cout << stck[i] << std::endl;
}
}
Stack::Stack (const Stack &ob)
{
cout<<"Copy constructor allocating stackPtr)"<<endl;
stck = new string;
*stck = *ob.stck;
}
//функция выделения дополнительной памяти
void Stack::Resize(int idx)
{
int new_size = sz;
while (new_size < idx)
new_size *=2;
string *new_arr = new string[new_size];
for(int i = 0; i < sz; i++)
new_arr[i] = stck[i];
delete[] stck;
stck = new_arr;
sz = new_size;
}
int main()
{
cout<<"Enter the size of the stack"<<endl;
int n;
cin>>n;
Stack mystck(n);
string str;
for(int i=0; i<n; i++)
{
cout<<"Enter an element"<<endl;
cin>>str;
mystck.Push(str);
}
for(int j = 0; j<n; j+2)
{
mystck.Pop();
mystck.Show(n);
}
return 0;
}
Can anybody help me with fixing that case?
I am trying to overload Insert() method in C++. Here is my code which i had come up with
Below is my List.h file
#ifndef _LIST_H_
#define _LIST_H__
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
class List
{
public:
List(size_t capacity = 5); // constructor - allocates dynamic array
~List(); // destructor
void insert(size_t position, int value);
void printArray();//Printing Array elements
private:
void resize(size_t new_size); // allocate new larger array
int *data_; // dynamic array
size_t size_; // size of dynamic array
size_t capacity_; // capacity of dynamic array
};
inline int& List::operator [] (size_t pos)
{
if (pos >= 0 && pos <= size_ - 1)
{
return data_[pos];
}
}
#endif _LIST_H_
This is my List.cpp file
#include "stdafx.h"
#include "List.h"
#include <iostream>
using namespace std;
List::List(size_t capacity)
{
data_ = new int[capacity];
capacity_ = capacity;
size_ = 0;
}
List::~List()
{
cout << "delete ";
delete[] data_;
}
void List::insert(size_t position, int value) {
if (size_ == capacity_)
{
resize(2 * capacity_);
}
if (position >= 0 && position <= capacity_ - 1)
{
data_[position] = value;
size_++;
}
}
void List::printArray()
{
size_t i;
for (i = 0; i < size_; i++)
{
cout << data_[i]<<" ";
}
}
void List::resize(size_t new_size)
{
int * temp;
size_t i;
capacity_ = new_size;
temp = new int[capacity_];
for (i = 0; i <= size_; ++i)
{
temp[i] = data_[i];
}
delete[] data_;
data_ = temp;
}
main method file
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//List d,a;
List *arr,*temp;
arr = new List(10);
temp = new List();
arr->insert(1, 3);
cout << "Printing array list after inserting: " << endl;
arr->printArray();
}
Output:
Testing Insert method:
Printing array list after inserting:
-842150451
Expected:
Testing Insert method:
Printing array list after inserting:
3
suppose if i have array like arr =[1,2,3,4]; arr->insert(2,-2). Output should be arr= [1,2,-2,3,4]
Can any one tell me why it is displaying a random number instead of inserted value and How to modify the code
You should change this line:
arr->insert(1, 3);
into:
arr->insert(0, 3);