I started learning OOP in C++. I try to solve a task like this:
Create a class - a list based on a one-size-fits-all array of integers. Assign a constructor, a destructor, the functions of adding an element to the top (end) of the list, selecting an element from the list by number, sorting the list, showing the elements of the list to the top and to the bottom of the list."
In the delete function, the compiler constantly knocks out the same error:
E0852 the expression must be a pointer to the full type of the object My_4_Project C:\Users\artem\source\repos\Project4\My_4_Project\Source.cpp
Here is my code:
#include <iostream>
#include <algorithm>
using namespace std;
class Array {
private:
int* a;
unsigned int size;
int b, c = 0, d;
public:
Array();
Array(int s);
~Array();
int& operator[](int index);
void setarray();
void getarray();
void add();
void delet();
void sort();
};
Array::Array() {
size = 10;
a = new int[size];
for (size_t i = 0; i != size; i++) {
a[i] = 0;
}
}
Array::Array(int s) {
if (s > 0) {
size = s;
a = new int[size];
for (size_t i = 0; i != size; i++) {
a[i] = 0;
}
}
else cout << "Size can't be negativ";
}
Array::~Array() {
delete[]a;
}
int& Array::operator[](int index) {
if (index <= size) {
return a[index];
}
}
void Array::setarray() {
for (size_t i = 0; i != size; i++) {
cin >> a[i];
}
}
void Array::getarray() {
for (size_t i = 0; i != size; i++) {
cout << a[i] << " ";
}
}
void Array::add()
{
/* ? ? ? */ ;
}
void Array::delet() {
cin >> b;
for (int i = 0; i < size; i++)
{
if (b == a[i])
c++;
if (c > 2) delete a[i];
}
cout << c;
}
void Array::sort() {
int temp;
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
for (int i = 0; i < size; i++) {
cout << a[i] << " ";
}
}
int main() {
cout << "Enter 10 number`s massive: ";
Array arr(10);
arr.setarray();
cout << endl;
arr.getarray();
cout << endl;
cout << "Sorted massive: ";
arr.sort();
cout << endl;
cout << "Witch symbol you wanna delete?: ";
arr.delet();
return 0;
}
The problem is that delete does not work as you think:
You can delete an object that you previously created with new (new returns a pointer, and delete expect that same pointer).
You can delete[] something that you previously created with new[]
But no mixing: you cannot delete an individual element when it was part of an array created with new[]
I will not do the exercise for you but the trick is to:
find the index of the duplicate element you want to get rid off,
copy every elements afterwards to one index before (i.e. a[j]=a[j+1], of course, making sure that j+1<size )
reduce the size by one.
So something like:
void Array::delet() {
cin >> b; // better put this in main() and pass it as argument
for (int i = 0; i < size; i++)
{
if (b == a[i])
{ // it'll be more than a single statement
c++;
if (c > 2) // found a duplicate
{ // NO delete a[i];
... // insert a loop to copy the next ones
// and reduce the size
... // EXTRA CAUTION: in this case the next element
// is again at offset i and not i++
}
}
}
cout << c; // ok, you can display the number of occurences counted
}
Related
So I have an assignement to write a version of the vector library without using it. I need to use dynamically allocated arrays, However their destructor is causing errors. Here is my code:
class orderedVector {
friend ostream& operator<<(ostream&, const orderedVector&);
friend istream& operator>>(istream&, orderedVector&);
public:
orderedVector(int = 9);
~orderedVector();
int getSize() const;
int getCapacity() const;
void doubleCapacity();
bool find(int) const;
void insert(int);
void remove(int);
void findSum(int);
private:
int size;
int capacity;
int* ptr;
};
orderedVector::orderedVector(int c) {
capacity = c;
size = 0;
ptr = new int[c];
}
orderedVector::~orderedVector() {
delete[] ptr;
}
int orderedVector::getSize() const {
return size;
}
int orderedVector::getCapacity() const {
return capacity;
}
void orderedVector::doubleCapacity() {
int newCapacity = capacity * 2;
orderedVector temp(capacity);
for (int i = 0; i < size; i++) {
temp.ptr[i] = ptr[i];
}
ptr = new int[newCapacity];
for (int i = 0; i < size; i++) {
ptr[i] = temp.ptr[i];
}
capacity = newCapacity;
}
bool orderedVector::find(int number) const {
for (int i = 0; i <= size; i++)
if (number == ptr[i])
return true;
return false;
}
void orderedVector::insert(int number){
if (find(number)) {
return;
}
if (size == capacity)
doubleCapacity();
if (size == 0)
ptr[0] = number;
else {
int checkpoint = size;
for (int i = 0; i < size; i++) {
if (number < ptr[i]) {
checkpoint = i;
break;
}
}
for (int i = size-1; i >= checkpoint; i--) {
ptr[i + 1] = ptr[i];
}
ptr[checkpoint] = number;
}
size++;
}
void orderedVector::remove(int number) {
if (find(number) == false)
cout << "Number does not exist in the vector.\n";
else {
int checkpoint = 0;
for (int i = 0; i <= size; i++)
if (ptr[i] == number)
checkpoint = i;
for (int i = checkpoint; i < size; i++)
ptr[i] = ptr[i + 1];
}
ptr[size] = 0;
size--;
}
void orderedVector::findSum(int number) {
for (int i = 0; i <= size; i++) {
for (int j = i+1; j <= size; j++) {
if (ptr[i] + ptr[j] == number) {
cout << "The two numbers that have a sum of " << number
<< " are " << ptr[i] << " and " << ptr[j] << endl;
return;
}
}
}
cout << "No two numbers found that give a sum of " << number << endl;
}
ostream& operator<<(ostream& output, const orderedVector& vector) {
for (int i = 0; i < vector.size; i++)
output << vector.ptr[i] << " ";
output << endl;
return output;
}
istream& operator>>(istream& input, orderedVector& vector) {
int x = 0;
for (int i = 0; i < vector.capacity; i++) {
input >> x;
vector.insert(x);
}
return input;
}
It appears that when I initialize an element, and the array is completely filled, I get this error:
HEAP CORRUPTION DETECTED, CRT detected that the application wrote to memory after end of heap buffer.
I know it's the destructor because when I remove it, no errors occur.
Also, when my vector element is not completely filled (the capacity is bigger than the size), no error occurs.
I would like to know how to fix this, or how the delete operator works in general, and why it causes an error if I fill my dynamically created array.
A dynamic allocation may be deallocated at most once. As such, when you deallocate in a destructor, it is important to establish a class invariant that at most one instance uniquely owns the same pointer. If such invariant is violated, then the destructors of those instances may attempt to delete same pointer twice, which leads to undefined behaviour. Which is bad.
Your class orderedVector indeed deallocates in its destructor. However, the (implicitly generated) copy constructor of the class copies the member variable, which violates the class invariant of unique ownership.
You failed to provide a MCVE, but it is reasonable to guess that your program makes a copy of an instance of orderedVector, leading to undefined behaviour due to multiple delete of the same pointer.
The solution is to either make the class non-copyable and non-movable, or follow the rule of 3 (or 5) i.e. implement the copy (and move) constructors and assignment operators in a way that enforces the invariant of unique ownership.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am writing a dynamic matrix class that stores each non-zero value as a List of 3 elements [row,column,value]
I made a dynamic array class called "List", and class"Matrix" a List of list pointers.
My code to transpose the Matrix works:
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
it works when written directly in main() but gives error when in stand alone function. can anyone explains why and how to fix it?
Full code:
#include <iostream>
using namespace std;
class List //a dynamic int pointer array
{
private:
int capacity;
int numOfElem;
int *arr;
//initialize all values in capacity to 0
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = 0;
}
}
//double the capaicty, then initialize
void expand()
{
capacity *= 2;
int *tempArr = new int[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
List()//constructor
{
capacity = 10;
numOfElem = 0;
arr = new int[capacity];
}
~List()//destrcutor
{
delete[] arr;
}
//add int to the end of List
void append(int newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
//Copy all element of an input list to the end of List
void copy(List list)
{
for (int i = 0; i < list.getNumOfElem(); i++)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = list.getAt(i);
}
}
//get reference of the int at an index in te list
int* getAddress(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return &arr[index];
}
//change the value of at specific index
void set(int index, int value)
{
arr[index] = value;
}
//get int at an index in te list
int getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
void displayList()
{
for (int i = 0; i < numOfElem; i++)
{
cout << arr[i] << " ";
}
}
};
class Matrix //a List of list pointers
{
private:
int capacity;
int numOfElem;
List* *arr;
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = new List;
}
}
void expand()
{
capacity *= 2;
List* *tempArr = new List*[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
Matrix()
{
capacity = 10;
numOfElem = 0;
arr = new List*[capacity];
}
~Matrix()
{
delete[] arr;
}
void append(List* newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
void set(int index, List* value)
{
arr[index] = value;
}
List* getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
};
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
int main()
{
int m, n, input;
cout << "Please enter the number of rows and columns of the matrix :\n";
cin >> m >> n;
Matrix tripleListMatrix;
int k = 0;
cout << "Please enter the matrix : \n";
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> input;
if (input != 0)
{
tripleListMatrix.append(new List);
(*(tripleListMatrix.getAt(k))).append(i + 1);
(*(tripleListMatrix.getAt(k))).append(j + 1);
(*(tripleListMatrix.getAt(k))).append(input);
k++;
}
}
}
cout << "The triple list of matrix is:\n";
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
cout << "\n\n";
//transpose(tripleListMatrix);
//the code below is the same as in the function transpose but transpose gives error
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
//cout << "\t" << list;
cout << "\n";
}
cout << "\n\n";
//checking that tripleListMatrix is unchanged
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
return 0;
}
List* *arr;
When you call transpose(), it makes a copy Matrix because you're not passing by reference. That copy just has a copy of the address for your List, not it's own List object. When the destructor runs on the copy, it clears up the allocated memory, but the original Matrix object in main still points to that same memory. When that object goes away, its destructor tries to free the same memory again and that's bad.
You probably meant:
void transpose(Matrix const & tripleList)
So that no copy is made when calling transpose(), but you should also explicitly delete the copy construtor of Matrix so it cannot be called
Matrix(Matrix const &) = delete;
or make an explicit Matrix copy constructor that makes a deep copy of the memory.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So, this is just few methods from my myArray.cpp class. It gives me error on
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
these above code(error - which is non-class type double). can anyone please help me? I'm trying to copy an array to the object array
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
That's my main.cpp class
#include <iostream>
#include "myArray.h"
//#include "myArray.cpp"
using namespace std;
int main (int argc, char **argv)
{
cout << "**************Testing Default Constructor*****************" << endl;
myArray A1;
cout << "A1: ";
A1.print();
cout << "**************Testing Alt Constructor 1*****************" << endl;
myArray A2(5,0);
cout << "A2: ";
A2.print();
cout << "**************Testing init*****************" << endl;
A2.init();
cout << "A2 after init: ";
A2.print();
int size = 5;
double *temp = new double[size];
for(int i = 0; i < size; i++)
{
temp[i] = i;
}
cout << "**************Testing Alt Constructor 2*****************" << endl;
myArray A3(temp, size);
cout << "A3: ";
cout << A3.getSize();
cout << endl;
cout << "Fe";
A3.print();
That's my myArray.cpp class
#ifndef MYARRAY_H_INCLUDED
#define MYARRAY_H_INCLUDED
/***************************************************************************
* myArray class header file
***************************************************************************/
class myArray
{
public:
myArray();
myArray(int,double);
myArray(double*, int);
~myArray();
int getSize() const;
bool equal(const myArray &rhs) const;
void setData(int index, double value);
void insert(int, double);
void remove(int);
double get(int);
void clear();
int find(double);
bool equals(myArray&);
void print() const;
void init();
double getData(int index) const;
// void init();
// void print() const;
void expand();
private:
int size;
double *arr;
void setSize(int value);
};
#endif // MYARRAY_H_INCLUDED
That's my myArray.cpp class where I'm getting the error in the default paramaterized constructor
#include "myArray.h"
#include <iostream>
using namespace std;
myArray::myArray() : size(0) {
// size = 10;
arr = new double [size];
}
/*myArray::myArray(int _size) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = i;
}
} */
myArray::myArray(int _size, double value) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = value;
}
}
/*myArray::myArray(myArray* temp, int size)
{
setSize(temp.getSize());
for (int i = 0; i < getSize(); i++) {
setData(i, temp.getData(i));
}
} */
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
//double arr[size];
// arr = new double[size];
// p = orig;
// for(int i = 0;i<size;i++)
// {
// arr[i] = orig[i];
// cout << arr[i] << " ";
// }
// cout << endl;
// setSize(size);
// for (int i = 0; i < getSize(); i++)
// setData(i, orig.getData(i));
// cout << "hell";
// for (int i = 0; i < size; i++) {
// arr[i] = myArray[i];
// cout << arr[i];
//}
// arr = myArray;
}
myArray::~myArray() {
delete [] arr;
}
int myArray::getSize() const {
return size;
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
void myArray::print() const {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
void myArray::expand() {
double *localArray = new double[size + 1];
for (int i = 0; i < size; i++) {
localArray[i] = arr[i];
}
localArray[size] = size;
delete [] arr;
setSize(size + 1);
arr = localArray;
// myArray = new int[size];
//
// //Is this a deep-copy or a shallow-copy?
// //Can you replace one with the other?
// //What are the advantages and disadvantages?
// for(int i=0; i < size; i++) {
// myArray[i] = localArray[i];
// }
// delete [] localArray;
}
bool myArray::equal(const myArray& rhs) const {
bool result(true);
if (getSize() != rhs.getSize()) {
result = false;
} else {
for (int i = 0; i < getSize(); i++) {
if (getData(i) != rhs.getData(i)) {
result = false;
}
}
}
return result;
}
void myArray::init()
{
cout << "Enter the " << size << " elements to populate the array " << endl;
for(int i = 0;i<getSize();i++)
{
int value;
cin >> value;
setData(i,value);
}
}
Sorry I somehow I thought you wanted help with a runtime error but you want help with the compile errors.
The compile error in this part of the code
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
is specifically about the orig.getSize() part. orig is of type double* (pointer to double) and pointers do not have member functions only classes do which is why the compiler says: "which is non-class type double"
Actually there is no way in c++ to know from a pointer to how many elements it points but luckily your function already has a parameter size which i guess is meant to pass in the size of the orig array. So that line should be setSize(size);
Now two lines lower you get a similar error on setData(i,orig.getData(i)); orig is still a double* so it still doesn't have member functions. The correct way is setData(i, orig[i]);
EDIT:
BTW, i quick look through the rest of your code shows me that your setSize method doesn't allocate an array of appropriate size so you should fix that to.
#include<iostream>
using namespace std;
class darray
{
private:
int n; // size of the array
int *a; // pointer to the 1st element
public:
darray(int size)
{
n = size;
a = new int[n];
}
~darray(){ delete[] a; }
void get_input();
int get_element(int index);
void set_element(int index, int value);
int count(){ return n; }
void print();
};
void darray::get_input()
{
for (int i = 0; i < n; i++)
{
cin >> *(a + i);
}
}
int darray::get_element(int index)
{
if (index == -1)
index = n - 1;
return a[index];
}
void darray::set_element(int index,int value)
{
a[index] = value;
}
void darray::print()
{
for (int i = 0; i < n; i++)
{
cout << a[i];
if (i < (n - 1))
cout << " ";
}
cout << endl;
}
// perform insertion sort on the array a
void insertion_sort(darray d)
{
int v = d.get_element(-1); // v is the right-most element
int e = d.count() - 1; // pos of the empty cell
// shift values greater than v to the empty cell
for (int i = (d.count() - 2); i >= 0; i--)
{
if (d.get_element(i) > v)
{
d.set_element(e,d.get_element(i));
d.print();
e = i;
}
else
{
d.set_element(e, v);
d.print();
break;
}
}
}
int main()
{
int s;
cin >> s;
darray d(s);
d.get_input();
insertion_sort(d);
system("pause");
return 0;
}
I use the darray class to make a array of size n at runtime. This class gives basic functions to handle this array.
This programs says debugging assertion failed at the end.
It gives this error after ruining the program.Other than that the program works fine. What is the reason for this error ?
You need to declare and define a copy constructor:
darray::darray(const darray& src)
{
n = src.n;
a = new int[n];
for (int i = 0; i < n; i++)
{
*(a + i) = *(src.a + i);
}
}
I keep getting the error in VS 2100 "CRT detected that the application wrote to memory before start of heap buffer"
Can anyone help? My int Main is all the way on the bottom. The error occur when the delete [] command is run on the operator= function
#include "intset.h"
const int MAXINITIALSIZE = 5;
int IntSet::numOfArray = 0;
IntSet::IntSet(int a, int b, int c, int d, int e)
{
numOfArray++;
int tempArray[] = {a, b, c, d, e};
size = determineHighest(tempArray) + 1; //determines largest int
cout << "size is " << size << endl;
arrayPtr = new bool[size]; //creates array of bool
for (int i = 0; i < size; i++) //fill bool array
{
arrayPtr[i]= false; //arrayptr is a bool pointer created in the header
}
for (int i = 0; i < MAXINITIALSIZE; i++)
{
arrayPtr[tempArray[i]]= true;
}
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
}
IntSet::IntSet(const IntSet &intsetObject)
{
numOfArray++;
size = intsetObject.size;
arrayPtr = new bool[size];
for (int i = 0; i < size; i++)
{
if (intsetObject.arrayPtr[i])
arrayPtr[i] = intsetObject.arrayPtr[i];
}
}
IntSet::~IntSet()
{
--numOfArray;
delete [] arrayPtr;
arrayPtr = NULL;
}
int IntSet::determineHighest(int tempArray[])
{
int temp = tempArray[0];
for (int i = 1; i < MAXINITIALSIZE; i++)
{
if (tempArray[i] > temp)
temp = tempArray[i];
else
continue;
}
return temp;
}
IntSet& IntSet::operator=(const IntSet &intsetObject) //ask about IntSet&
{
cout << "inside operator=" << endl;
if (&intsetObject != this)
{
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
delete [] arrayPtr; //HEAP ERROR HERE!
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
size = intsetObject.size
arrayPtr = new bool[size]();
for (int i = 0; i < size; i++)
{
if (intsetObject.arrayPtr[i])
arrayPtr[i] = intsetObject.arrayPtr[i];
}
}
return *this;
}
ostream& operator<<(ostream &output, const IntSet &intsetObject)
{
output << "{ ";
for (int i = 0; i < intsetObject.size; i++)
{
if (intsetObject.arrayPtr[i] == true)
{
output << i << " ";
}
else
continue;
}
output << "}";
return output;
}
//main
#include "intset.h"
int main() {
IntSet object2(9);
IntSet object4(3,6);
object4 = object2;
return 0;
}
This can only happen if arrayPtr is accessed with a negative index. I suspect your defaults for a,b,c,d,e are -1 in the declaration for IntSet::IntSet, so it is writing to arrayPtr[-1] in the set-true loop. Check for tempArray[i] >= 0 there.
Also, you can't print the array after you have deleted it, so you should remove those lines after the delete, although they should be "harmless" in that only garbage will be printed, but who knows - the OS could release the page containing the array and it could segfault your program.
Finally, you should not test if (intsetObject.arrayPtr[i]) in the copy & = operators. Otherwise all "false" elements in the source array become uninitialized in the destination array (new bool[size] does not initialize the array to all false).