class SmallVector
{
public:
SmallVector(void);
SmallVector( const int *tempArr, int arrSize );
SmallVector( const SmallVector &tempObj );
int size(void) const;
int capacity(void) const;
void push_back(int number); // ++
void push_back(int *tempArr, int arrSize ); // ++
int pop_back(void);
int operator[](int index) const;
SmallVector operator+(const SmallVector &tempObj);
SmallVector operator*(int times);
void printObj(void) const;
bool isFull(void);
private:
int staticIndex; // It refers to total element in the static part of the vector
int dynamicIndex; // it refers to index number of dynamic array(it also refers to number of elements in dynamic section)
int dynamicSize; // allocated memory for dynamic array
int staticArray[32];
int *dynamicArray;
void expand(int newSize);
void shrink(void);
};
SmallVector SmallVector::operator+(const SmallVector &tempObj)
{
int i;
int totalSize = ( this->size() + tempObj.size() );
if( totalSize == 0 ) // arguments of sum operator are empty vector
return SmallVector(); // default constructor is executed
int *tempArray = new int[totalSize];
for(i = 0; i < this->size(); ++i)// filling tempArray with first operand
{
if(i <= 31)
tempArray[i] = staticArray[i];
else
tempArray[i] = dynamicArray[i - 32];
}
for(int j = 0; j < tempObj.size(); ++j, ++i)
tempArray[i] = tempObj[j];
return SmallVector(tempArray, totalSize); // error is here
}
SmallVector::SmallVector( const SmallVector &tempObj )
{ // copy constructor
staticIndex = 0;
dynamicIndex = 0;
dynamicSize = 0;
if( tempObj.size() > 32 ){
dynamicSize = tempObj.size() - 32;
dynamicArray = new int[dynamicSize];
}
for( int i = 0; i < tempObj.size(); ++i ){
if( i <= 31 ){ // filling static array
staticArray[staticIndex] = tempObj[i];
++staticIndex;
}
else{
dynamicArray[dynamicIndex] = tempObj[i];
++dynamicIndex;
}
}
}
This is actually realizing a vector project ,but I encountered very interesting problem. If argument of copy constructor is not const, operator overloading + gives me an error when returning temporary instance of the class. I think, the compiler is confused about the constructors.
Error : no matching function for call to SmallVector::SmallVector(SmallVector&)
this error occurs in return statements in operator overloading +.
Related
I'm trying to build my own Matrix class and have overloaded the "*=" operator.
I am however running into problems with some pointer loss. I don't understand where my problem is at the moment.
Is it because I'm creating a new Matris "new_m" and this only lives inside the scope of the function? So I can't set the new pointer to data to the implied (*this) object?
Below is the code for my *= operator.
Matris<T> &operator*=(const Matris<T> &m){
//if(m_cols != m.m_rows || m.rows != m.m_cols) throw new std::out_of_range("When multiplying two matrices they have to have be \"opposites\", that is one can be 1x2 and other one 2x1.");
//else{
unsigned int new_cap = m_rows * m.m_cols;
Matris<T> new_m(sqrt(new_cap));
new_m.m_vec = (T*) realloc(new_m.m_vec, new_cap*sizeof(T));
std::memset (new_m.m_vec, 0, sizeof(T) * new_cap);
for(size_t i = 0; i < m_rows; i++){
for (size_t j = 0; j < m.m_cols; j++) {
for (size_t k = 0; k < m_cols; k++) {
new_m(i,j) += (*this)(i,k) * m(k,j);
}
}
}
m_vec = new_m.m_vec;
//}
return *this;
}
And this is how I store and save my data in my Matris class:
private:
size_t m_rows;
size_t m_cols;
size_t m_capacity;
T * m_vec;
This is the constructor that is being called with an int:
explicit Matris(const unsigned int i){ //constructor with one integer, has to be integer, can't be negative or float.
m_rows = i;
m_cols = i;
m_capacity = i*i;
m_vec = (T*) malloc(i*i*sizeof(T));
std::memset (m_vec, 0, sizeof (T) * i*i);
}
m_vec = new_m.m_vec;
This makes m_vec point to part of the temporary object that's about to be destroyed. You want:
*this = new_m;
I've been trying to make a dynamic array. My main method calls push_back() to add ints to an array 50 times. The push_back() method calls the grow_if_needed() method if the size of the array needs to be doubled. The size() method returns the current capacity of the array. And the toString method is for printing the array as a string. I keep getting this error at the end of the grow_if_needed() method.
#include <string>
class ArrayList
{
private:
static int capacity;
static int count;
public:
int& operator [](int i);
int *arrayPtr = new int[1];
ArrayList();
int * push_back(int m);
int * grow_if_needed();
int * erase(int m);
int size();
std::string toString();
};
#include "ArrayList.h"
using namespace std;
int ArrayList::capacity = 1;
int ArrayList::count = 0;
int & ArrayList::operator[](int i)
{
return arrayPtr[i];
}
ArrayList::ArrayList()
{
arrayPtr[0] = 0;
}
int * ArrayList::push_back(int m)
{
if (count == size()) {
grow_if_needed();
}
for (int i = size() - 1; i >= 0; i--) {
arrayPtr[i + 1] = arrayPtr[i];
}
arrayPtr[0] = m;
count++;
return arrayPtr;
}
int * ArrayList::grow_if_needed() {
int k;
capacity = size() * 2;
int * tempArray = new int[capacity];
for (k = 0; k < count; k++) {
tempArray[k] = arrayPtr[k];
}
while (k != capacity) {
tempArray[k] = 0;
k++;
}
delete [] arrayPtr;
arrayPtr = tempArray;
return arrayPtr;
}
int ArrayList::size()
{
return capacity;
}
string ArrayList::toString()
{
string num = "";
for (int i = 0; i <= size() - 1; i++) {
num += std::to_string(arrayPtr[i]) + " ";
}
return num;
}
In your push_back function you have this loop:
for (int i = size() - 1; i >= 0; i--) {
arrayPtr[i + 1] = arrayPtr[i];
}
Here size() - 1 is the top index, so in the first iteration when you do i + 1 you are out of bounds.
Also, this function is called push_back, but it attempts to add to the front? If it added to the end (the "back") you would not need the loop, and your problem would "magically" disappear.
I get this error while running the following program (it execute the code perfectly but looks like there are some issues about pointers/memory). thanks in advance for your help...
This is the message i get:
REVIEW(8310) malloc: * error for object 0x100103b80: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
(lldb)
My code:
In file Matrix.h
template <typename T>
class Matrix
{
private:
T** M;
// unsigned numCol, numRow;
unsigned minRowIndex, maxRowIndex;
unsigned minColIndex, maxColIndex;
public:
Matrix(); // default constructor
Matrix(const unsigned& _numRow,
const unsigned& _numCol,
const T& value,
const unsigned& _minRowIndex = 0,
const unsigned& _minColIndex = 0);
~Matrix();
void Print();
T& operator() (const unsigned& row, const unsigned& col);
};
template<typename T>
Matrix<T> :: Matrix()
{
maxRowIndex = 9;
maxColIndex = 9;
unsigned i,j;
M = new T*[maxRowIndex + 1];
for (i = minRowIndex; i < maxRowIndex; i++)
M[i] = new T[maxColIndex + 1];
for (i = minRowIndex; i < maxRowIndex; i++)
for (j = minColIndex; j < maxColIndex; j++)
M[i][j] = 0;
}
template<typename T>
Matrix<T> :: Matrix( const unsigned& _numRow,
const unsigned& _numCol,
const T& value,
const unsigned& _minRowIndex,
const unsigned& _minColIndex)
{
minRowIndex = _minRowIndex;
minColIndex = _minColIndex;
maxRowIndex = _minRowIndex + _numRow - 1;
maxColIndex = _minColIndex + _numRow - 1;
unsigned i,j;
M = new T*[maxRowIndex + 1];
for (i = minRowIndex; i <= maxRowIndex; i++)
M[i] = new T[maxColIndex + 1];
for (i = minRowIndex; i <= maxRowIndex; i++)
for (j = minColIndex; j <= maxColIndex; j++)
M[i][j] = value;
}
template<typename T>
Matrix<T> :: ~Matrix()
{
for (unsigned i = 0; i <= maxRowIndex; i++)
delete[] M[i];
delete[] M;
}
template<typename T>
void Matrix<T> :: Print()
{
unsigned i,j;
for (i = minRowIndex ; i <= maxRowIndex; i++)
for (j = minColIndex; j <= maxColIndex; j++)
{
cout << M[i][j] << " ";
if (j == maxColIndex)
cout << endl;
}
cout << endl;cout << endl;
}
template<typename T>
T& Matrix<T> :: operator() (const unsigned& row, const unsigned& col)
{
return M[row][col];
}
In file main.cpp
#include "Matrix.h"
using namespace std;
int s(Matrix<int> L)
{
return L(2,2);
}
int main()
{
Matrix<int> L (5,5,100);
cout << "L(2,2) = " << s(L) << endl << endl;
return 0;
}
Classes that allocate fields using new and delete should have copy constructors and overload operator=. Failing to do so will use the default forms where fields are simply copied.
In your case, T** M is copied during the call to s(L) and upon return, the copy is destructed, causing deletes for all the arrays. At the end of main, another destruction takes place, but now the pointers refer to already freed blocks.
For function s, you might also pass a reference to avoid copying (but this doesn't solve the general problem).
I've created a class in C++ to deal with arrays of 0s and 1s. In private attributes I have a size, a type and an array of integer for the size specified.
My problem is that the values in the array is being modified every time I call the constructor again. In more detailled, I create a first object with the constructor, then a second one and doing this modifies the first one!
I've tried to play around with pointers, the new operator, const pointers to const object, nothing works! Idependently of the size of array I chose, it's always the third, then the sixth, then the ninth, etc value of the array that is modified to the value of the size.
any suggestion appreciated.
some extracts from my code:
class SArray
{
private:
int SArray_Size;
int DType;
int Table[];
public:
//complete constructor
SArray::SArray(const int& tsize, const int& ttype)
{
SArray_Size = tsize;
DType = ttype;
if (ttype == 0) //random array with integer values between 0 and 1
{
for (int i = 0; i < getSize(); i++)
{
Table[i] = rand() % 2;
}
}
if (ttype == 1) //default array with only 1s
{
for (int i = 0; i < getSize(); i++)
{
Table[i] = 1;
}
}
}
};
int main()
{
const int NbRes = 15;
//reset the random number generator
srand(time(0));
const SArray test3(NbRes,1);
(test3).print();
const SArray test1(NbRes,1);
(test1).print();
(test3).print();
return 0;
}
The culprit is int Table[] - you have not specified how large your table is.
You should really replace it with std::vector<int> Table; and initialize it with tsize.
For instance:
#include <vector>
class SArray
{
private:
int DType;
std::vector<int> Table;
public:
const size_t getSize() const { return Table.size(); }
public:
SArray::SArray(const int tsize, const int ttype) :
DType(ttype), Table(tsize)
{
int i, n = getSize();
switch( ttype )
{
case 0:
for (i = 0; i < n; ++i)
Table[i] = rand() % 2;
break;
case 1:
for (i = 0; i < n; ++i)
Table[i] = 1;
break;
}
}
};
You must allocate memory for "Table". For example:
SArray::SArray(const int& tsize, const int& ttype)
{
SArray_Size = tsize;
DType = ttype;
Table= new int[tsize];
...
Don't forget to free it in destructor.
//output is "01234 00000" but the output should be or what I want it to be is
// "01234 01234" because of the assignment overloaded operator
#include <iostream>
using namespace std;
class IntArray
{
public:
IntArray() : size(10), used(0) { a= new int[10]; }
IntArray(int s) : size(s), used(0) { a= new int[s]; }
int& operator[]( int index );
IntArray& operator =( const IntArray& rightside );
~IntArray() { delete [] a; }
private:
int *a;
int size;
int used;//for array position
};
int main()
{
IntArray copy;
if( 2>1)
{
IntArray arr(5);
for( int k=0; k<5; k++)
arr[k]=k;
copy = arr;
for( int j=0; j<5; j++)
cout<<arr[j];
}
cout<<" ";
for( int j=0; j<5; j++)
cout<<copy[j];
return 0;
}
int& IntArray::operator[]( int index )
{
if( index >= size )
cout<<"ilegal index in IntArray"<<endl;
return a[index];
}
IntArray& IntArray::operator =( const IntArray& rightside )
{
if( size != rightside.size )//also checks if on both side same object
{
delete [] a;
a= new int[rightside.size];
}
size=rightside.size;
used=rightside.used;
for( int i = 0; i < used; i++ )
a[i]=rightside.a[i];
return *this;
}
I think that the problem is that nowhere in your code sets used to anything other than 0 so when you loop from 0 to used nothing is copied.
Do you mean to set used when you assign to an element in operator[] ?
Also, if it's necessary to define a destructor and a copy-assignment operator then you usually (and in this case) need to supply a copy-constructor as well.