Operator overload for vector function c++ - c++

I'm sure this question is super simple, I'm just quite new to programming and to C++ in general.
For my class, we are making a Vector with a class template. My professor has supplied the .h file and we have to write the integrated .cpp file. Heres the .h file:
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <new> // Needed for bad-alloc exception
#include <cstdlib> // Needed for the exit function
using namespace std;
template <class T>
class SimpleVector
{
private:
T *aptr; // To point to the allocated array
int arraysize; // Number of elements in the array
void memError(); // Handles memory allocation errors
void subError(); // Handles subscripts out of range
public:
SimpleVector()
{
aptr = 0;
arraysize = 0;
}
SimpleVector(int s);
SimpleVector(const SimpleVector & sv);
~SimpleVector();
int size() const
{
return arraysize;
}
T getElementAt(int sub);
T &operator[](const int);
};
#endif //SIMPLEVECTOR_H
And here is my implementation:
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
SimpleVector<T>::SimpleVector(int s)
{
if(s<1)
{
arraysize=1;
}
else
{
arraysize=s;
}
try
{
aptr = new T [arraysize];
}
catch (bad_alloc)
{
memError();
}
for(int i=0;i<arraysize;i++)
{
aptr[i]=0;
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
void SimpleVector<T>::memError()
{
cout<<"Error: cannot allocate memory."<<endl;
exit(EXIT_FAILURE);
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
void SimpleVector<T>::memError()
{
cout<<"Error: cannot allocate memory."<<endl;
exit(EXIT_FAILURE);
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
T SimpleVector<T>::getElementAt(int sub)
{
return aptr[sub];
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
SimpleVector<T>::~SimpleVector()
{
delete aptr;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
void SimpleVector<T>::subError()
{
cout<<"Subscripts out of range."<<endl;
exit(EXIT_FAILURE);
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class T>
SimpleVector<T>::SimpleVector(const SimpleVector & sv)
{
aptr=sv.aptr;
}
template <class T>
T<T>&::operator[](const int &)
{
return aptr[];
}
I know that my overload operator is way off and makes no sense, I just dont understand the syntax well enough to even know where to begin. Obvisouly, the operator should return the value of the aptr at whatever index was passed in through [].

There are multiple problems with your code, including:
Not catching bad_alloc correctly (never catch an exception class by value, always by reference).
duplicate definitions of memError(). You need to remove one of them.
~SimpleVector() using delete instead of delete[].
SimpleVector(const SimpleVector &) making a shallow copy of sv.aptr when it needs to make a deep copy instead.
getElementAt() not calling subError() if sub is out of range. Historically, operator[] doesn't perform range checking, but you can if you want/need to.
But, to answer the specific question you asked, your operator[] is implemented all wrong. Aside from the obvious syntax error in writing its definition, and that the definition does not match the declaration, internally it simply needs to do the same return action that the getElementAt() method is doing, eg:
template <class T>
T& SimpleVector<T>::operator[](const int sub)
{
return aptr[sub];
}

Related

"pointer being freed was not allocated" How can I find my wrong access to memory?

Firstly, I have to print the value of Funcion "Ranking" which of parameter is Stack!
But my compiler says
I think that I delete memory which is not allocated. But, I can't find when I delete that memory....
Please help me the point I wrongly access memory.
P.S. I want to make a program that receive ints or strings and, put ints or strings into stack.
And use Ranking function as a Stack, the result would be,
For ints, how many numbers in stack which exceed first number of stack .
For strings, how many strings in stack which are later order than first string of stack.(The order of string objects is determined in the lexicographic order.)
For example, if inputs are 4 1 +2 5 3 -1 6 and the results is 2 (because 5 and 6 are bigger than first 4)
For example, if inputs are "to be or not to be" the results is 0 ( because there is no later order string than "to")
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const size_t SIZE = 100;
using namespace std;
template <class T>
class Stack
{
public:
Stack(size_t size = SIZE);
Stack(const Stack<T>& s);
const Stack<T>& operator = (const Stack<T>& s); ~Stack();
bool isfull();
bool isEmpty();
void push(T d);
T pop();
T Elem(size_t i);
// int Ranking(T obj);
private:
T *_data;
size_t _top, _size;
};
template <class T>
Stack<T>::Stack(size_t size) : _top(0), _size(size)
{
_data = new T[size];
}
template <class T>
Stack<T>::Stack(const Stack<T>& s) : _top(s._top), _size(s._size)
{
if (_data) delete[] _data;
_size = s._size;
_top = s._top;
_data = new T[_size];
for (int i = 0; i < _size; ++i)
_data[i] = s._data[i];
}
template <class T>
Stack<T>::~Stack()
{
delete [] _data;
}
template <class T>
bool Stack<T>::isfull()
{
return _top == _size;
}
template <class T>
bool Stack<T>::isEmpty()
{
return _top == 0;
}
template <class T>
void Stack<T>::push(T d)
{
if (! isfull())
_data[_top++] = d;
}
template <class T>
T Stack<T>::pop()
{
if (! isEmpty())
return _data[--_top];
throw -1;
}
template <class T>
T Stack<T>::Elem(size_t i)
{
return _data[i];
}
template <class T>
int Ranking(T obj)
{
int k = 0;
while(!obj.isEmpty())
{
if(obj.Elem(0).compare(obj.pop()) < 0 )
k++;
}
return k;
}
int main(void)
{
int k = 0;
int value = 0;
int num;
string s;
string line;
Stack<string> strs;
Stack<string> temps;
vector<int> nums;
while (getline(cin, line))
{
istringstream ins(line);
while (ins >> s)
{
strs.push(s);
}
nums.push_back(Ranking(strs));
}
}
In the body of your copy constructor, _data is initially uninitialised. if (_data) has undefined behaviour, which you have observed as delete[]ing an arbitrary pointer value.
There is never a previous allocation in a new object, so you don't need to delete[] anything. You declare (in a non-traditional way) but don't define a copy assignment operator.
I've also implemented a move constructor, which can reduce the number of copies you need.
Most of the bodies of your constructors can go, or be moved to the member initialiser. It is better to use a pre-defined algorithm rather than do it yourself.
#include <algorithm>
#include <utility>
template <class T>
Stack<T>::Stack(size_t size) : _data(new T[size]), _top(0), _size(size)
{}
template <class T>
Stack<T>::Stack(const Stack<T>& s) : _data(new T[s._size]), _top(s._top), _size(s._size)
{
std::copy_n(s._data, s._size, _data);
}
template <class T>
Stack<T>::Stack(Stack<T>&& s) : _data(std::exchange(s._data, nullptr)), _top(s._top), _size(s._size)
{
}
template <class T>
Stack<T>& Stack<T>::operator=(Stack<T> s) // nb: by-value argument, copies or moves
{
std::swap(_data, s._data);
_size = s._size;
_top = s._top;
return *this;
}

C++ segmentation fault when I have an Array inside an Array

I tried to implement my own class named Array that act mostly like a vector because I don't want to use std. It works well with basic classes but when I want to instantiate an Array of a class that contains an Array (class Scene for exemple) it stops the program saying "Windows stoped fonctionning"... When I try to search for the error with break points I saw that it says "segmentation fault" when the program is at the destructor.
Here's my classes :
Array.h
#ifndef NAME_ARRAY_H
#define NAME_ARRAY_H
#include <stdexcept>
#include <iostream>
#include "malloc.h"
template <class T>
class Array {
private:
T *m_array;
unsigned int m_tot_size;
unsigned int m_actual_size;
public:
Array(unsigned int size);
Array(Array<T> const& paste);
bool add(T var);
const T& get(unsigned int index);
bool remove(unsigned int index);
void kill();
unsigned int getActualSize() const;
unsigned int getTotalSize() const;
T* getArray() const;
T& operator[](unsigned int index);
Array<T>& operator=(Array<T> const& paste);
~Array();
};
//CONSTRUCTOR
template <class T>
Array<T>::Array(unsigned int size) : m_tot_size(size), m_actual_size(0) {
m_array = (T*) malloc(size * sizeof(T));
}
template <class T>
Array<T>::Array(Array<T> const &paste) : m_tot_size(paste.m_tot_size),
m_actual_size(paste.m_actual_size) {
m_array = new T(*(paste.m_array));
}
//METHODES PUBLIC
template <class T>
const T & Array<T>::get(unsigned int index) {
if (index >= m_actual_size || index < 0)
throw std::out_of_range("Index out of range");
return m_array[index];
}
template <class T>
bool Array<T>::remove(unsigned int index) {
if(index < m_actual_size && m_actual_size != 0) {
m_actual_size--;
m_array[index] = m_array[m_actual_size];
return true;
}
return false;
}
template <class T>
bool Array<T>::add(T obj) {
if (m_actual_size >= m_tot_size) {
T *temp;
temp = (T*) realloc(m_array,5*sizeof(T));
m_array = temp;
m_array[m_actual_size] = obj;
m_actual_size++;
m_tot_size += 5;
return false;
} else {
m_array[m_actual_size] = obj;
m_actual_size++;
return true;
}
}
template <class T>
void Array<T>::kill() {
free(m_array);
delete [] m_array;
m_array = nullptr;
m_actual_size = 0;
m_tot_size = 0;
}
//ACCESSOR
template <class T>
unsigned int Array<T>::getActualSize() const { return m_actual_size; }
template <class T>
unsigned int Array<T>::getTotalSize() const { return m_tot_size; }
template <class T>
T* Array<T>::getArray() const { return m_array; }
//OPERATOR
template <class T>
T& Array<T>::operator[](unsigned int index) { return m_array[index]; }
template <class T>
Array<T>& Array<T>::operator=(Array<T> const& paste) {
if(this != &paste) {
m_tot_size = paste.m_tot_size;
m_actual_size = paste.m_actual_size;
free(m_array);
delete [] m_array;
m_array = nullptr;
m_array = new T(*(paste.m_array));
}
return *this;
}
//DESTRUCTOR
template <class T>
Array<T>::~Array() {
free(m_array);
delete [] m_array;
m_array = nullptr;
}
Scene.cpp :
#include "Scene.h"
Scene::Scene(std::string sceneName) : m_name(sceneName), m_array_position(20) {
}
void Scene::update() {}
void Scene::render() {}
Scene::~Scene() {
//m_array_position.kill();
//m_array_systems.kill();
}
Scene.h
#ifndef NAME_SCENE_H
#define NAME_SCENE_H
#include <string>
#include <unordered_map>
#include "../components/Position.h"
#include "../utils/Array.h"
#include "../systems/System.h"
class Scene {
private:
std::string m_name;
Array<Position> m_array_position;
public:
Scene(std::string sceneName);
void update();
void render();
~Scene();
};
main
Array<Scene> scenes(1);
I think the problem is that the program destroy the Array and then try to destroy the Array (Position is just a struct) but I'm not sure and I don't know what to do to correct it. Can someone please help me ?
I see in a lot of places code like this:
free(m_array);
delete [] m_array;
This doesn't look good to me. When allocating and deallocating memory, you have to match the allocation method with the deallocation:
If you reserve memory with "malloc", you free it with "free"
If you reserve with "new", you deallocate with "delete"
If you reserve with "new []", then you free with "delete []"
You should only use one of the methods or, if you REALLY need to mix them, then you should keep something tracking which method you would need to free the memory.

error: 'template<class T> class Dynamic_Array' used without template parameters

I've been getting this error for some time, and I have no clue how to fix it.
I searched for similar problem here on stack overflow, but I've failed to find anything.
Source code:
template <typename T>
class Dynamic_Array
{
private:
T* actual_array;
unsigned int number_of_elements;
public:
Dynamic_Array() {}
~Dynamic_Array() {delete[] actual_array;}
unsigned int get_size() const {return number_of_elements;}
T& operator [](unsigned int index) {return actual_array[index];}
void operator +=(T&);
void operator -=(unsigned int);
};
template <typename T> /*Not sure if this is needed, but compiler doesn't mind, still prints the same error*/
void Dynamic_Array<T>::operator+=(T& object)
{
if(number_of_elements>1)
{
T* temp_array = new T[number_of_elements];
for(unsigned int i=0;i<number_of_elements;i++)
{
temp_array[i]=actual_array[i];
}
delete[] actual_array;
actual_array = new T[number_of_elements+1];
for(unsigned int i=0;i<number_of_elements;i++)
{
actual_array[i]=temp_array[i];
}
delete [] temp_array;
temp_array=NULL;
actual_array[number_of_elements]=object;
number_of_elements++;
}
else
{
number_of_elements++;
actual_array = new T[1];
}
}
void Dynamic_Array<T>::operator-=(unsigned int index)
{
T* temp_array = new T[number_of_elements-1];
for(unsigned int i=0, j=0;i<number_of_elements;i++)
{
if(i!=index)
{
temp_array[j]=actual_array[i];
j++;
}
}
delete[] actual_array;
number_of_elements--;
actual_array = new T[number_of_elements];
for(unsigned int i=0;i<number_of_elements;i++)
{
actual_array[i]=temp_array[i];
}
delete [] temp_array;
temp_array = NULL;
}
According to compiler, the error is present in line 18 (the empty one between "};" and "template"
As I said, I have no idea what I screwed up, so any help is appreciated.
When you define member functions outside of a class template declaration then you need to specify the template for each function. When you define
void Dynamic_Array<T>::operator-=(unsigned int index)
{
//...
}
You need to have the template part as well like
template <typename T>
void Dynamic_Array<T>::operator-=(unsigned int index)
{
//...
}
This has to be present for every function definition that you do out of line. A single template <typename T> at the start of all the definition does not apply to all of the function definitions.
Dynamic_Array is a template class so when defining operator+= and operator-= outside the scope of the class you need to provide template type as follows:
template<typename T> void Dynamic_Array<T>::operator+=(T& object) {
//...
}
template<typename T> void Dynamic_Array<T>::operator-=(unsigned int index) {
//...
}
Also, I should note that it is somewhat odd to have void as a return type for operator+= and operator-=, typically you should return a reference to the altered instance of this, i.e:
template<typename T> Dynamic_Array<T>& Dynamic_Array<T>::operator+=(const T& object) {
//...
}

initialize a member of some class in initialization list if the member is a template class

[Solved]: The problem was not in template class initialization, but with code-specific issue of using undefined macro inside a template class constructor. The compiler error did not complain about undefined symbol, but was (wrongfully) related to lambdas.
I've searched for an answer but couldn't find an exact one. The closest answer is here: C++ invoke explicit template constructor but I'm not sure if that is entirely related to my question.
And my question is, how can I initialize a member of structure B in initialization list if the member is a template class?
Header ClassA.h:
#ifndef _A_
#define _A_
#include <typeinfo>
#include <windows.h>
template<class Type> class A{
int u,v;
Type** pointer;
public:
A();
A(int number);
~A();
Type& operator[] (int i){
typeid(Type);
return *pointer[i];
}
Type& Get(int i)
{
typeid(Type);
return *pointer[i];
}
Type *GetPointer(int i)
{
typeid(Type);
return pointer[i];
}
Type* add ();
Type& add(Type *element);
Type& add(Type *element, int place);
void expand(int NewLength);
void swap(Type *element, int place);
void remove(int number);
void remove(Type *element);
void removePointer(int number);
void removePointer(Type *element);
};
template<class Type>A<Type>::A(){
u = 128;
v = 10;
}
template<class Type>A<Type>::A(int number){
//some thing to do with number;
u = number;
v = 10;
New( pointer, Type *[u] );
}
template <class Type> A<Type>::~A()
{
}
template <class Type> void A<Type>::expand(int NewLength)
{
Type **NewList = NULL;
NewList = new Type*[NewLength];
}
template <class Type> Type* A<Type>::add ()
{
pointer[u] = new Type;
}
template <class Type> Type& A<Type>::add(Type *element)
{
}
template <class Type> Type& A<Type>::add(Type *element, int place)
{
}
template <class Type> void A<Type>::swap(Type *element, int place)
{
}
template <class Type> void A<Type>::remove(Type *element)
{
}
template <class Type> void A<Type>::removePointer(int nume)
{
}
template <class Type> void A<Type>::removePointer(Type *element)
{
}
#endif
Header StructB.h:
#pragma once
#ifndef _B_
#define _B_
#include "ClassA.h"
struct C{
float x,y,z;
};
struct B{
private:
B(){
}
public:
int x,y;
A<B*> member1;
A<C> member2;
B(int X,int Y) : member1(5),member2(5) {
//initialize x,y
}
void Add(B* otherB){
B** _pOtherB = new B*; (*_pOtherB) = otherB;
member1.add(_pOtherB);
}
};
#endif
The compiler complains with this error (and some other errors, I can post them if nedded):
error C3493: 'number' cannot be implicitly captured because no default capture mode has been specified
Is there any way to do this, or some workaround perhaps?
Thanks in advance :D
Either the code you've given us isn't complete, or it is broken. This line:
New(pointer, Type *[u]);
seems to be referencing either some missing member method or global function, or it is simply invalid. The error message is kinda cryptic, but that's C++ for you.
I'm going to assume that New is some kind of macro, because no normal function (even a templated one) can take this sort of type definition as a parameter. You've not given us the definition of New, so there's no way we can tell. It is probably the absense of this macro (maybe a wrapper for some sort of memory debugging system?) that is causing the crazy error.
If I replace the New line with this:
pointer = new Type*[u];
the code compiles fine.

deallocation of pointers

I have a list pointer in type of A (called ListA) container a vector of pointers B. (Each A object is a container class that has a private attribute: std<vector> *B). Then, I declare a pointer (called C having the same type as A), make a for-loop through ListA to get all pointers B and put them in C. When I quit my program, I deallocate ListA first, ListA in turn deallocates their own vector of pointers B. Then I deallocate pointer C, but the program crashes.
I have debugged this a bit and know that pointer C at the time of deallocation points to nothing, so it doesn't know what to deallocate.
Am I doing wrong? Or what is the solution for my problems?
Sorry, I'll put my code below
//Class A
#pragma once
#include "MyContainer.h"
class B;
class A
{
public:
A();
~A();
MyContainer<B> *pListOfB;
}
A::A()
{
pListOfB = new MyContainer<B>;
}
A::~A()
{
if(pListOfB)
{
delete pListOfB;
pListOfB = NULL;
}
}
//Class C
#pragma once
#include "MyContainer.h"
class B;
class C
{
public:
C();
~C();
MyContainer<B> *pListOfB;
void getListOfB(MyContainer<A> *pListOfA);
}
C::C()
{
pListOfB = new MyContainer<B>;
}
C::~C()
{
if(pListOfB)
{
delete pListOfB;
pListOfB = NULL;
}
}
void C::getListOfB(MyContainer<A> *pListOfA)
{
for(pListOfA->isBegin(); !pListOfA->isEnd();)
{
A *pA = pListOfA->getNext();
for(pA->isBegin(); !pA->isEnd();)
{
B* pB = pA->*pListOfB->getNext();
pListOfB->add(pB);
}
}
}
//Class MyContainer
#pragma once
#include <vector>
template <class T>
class MyContainer
{
public:
MyContainer(void);
~MyContainer(void);
T* getNext();
void removeAll();
void add(T* t);
void isBegin();
bool isEnd();
private:
std::vector<T*> items;
typename std::vector<T*>::iterator it;
};
template <class T> MyContainer<T>::~MyContainer()
{
removeAll();
}
template <class T> void MyContainer<T>::add(T *t)
{
items.push_back(t);
}
template <class T> void MyContainer<T>::removeAll()
{
while(!isEmpty())
{
std::vector<T*>::iterator tempIt =items.begin();
T* t = (*tempIt);
items.erase(tempIt);
delete t;
t=NULL;
}
}
template <class T>
T* MyContainer<T>::getNext()
{
if(isEnd() || isEmpty())
return NULL;
return (T*)(*(it++));
}
template <class T>
void MyContainer<T>::isBegin()
{
it = items.begin();
}
template <class T>
bool MyContainer<T>::isEnd()
{
return it==items.end();
}
I do the following action:
1. Initial a list A object : MyContainer *pListOfA;
2. Insert B data to each A object in pListOfA
3. Initial C object
4. Call C object operation getListOfB to get B data from pListOfA.
5. Quit program
Program first dealloc pListOfA, each A then dealloc their own pListOfB. After that program dealloc C object in turn dealloc pListOfB attribute of C. But pListOfB point to nothing because pListOfA deallocs every data. So my program crash.
I fix by rem the line delete pListOfB in the dtor of class C but I got a warning memory leak at that line.
That's all my problem. Please show me the right way. Thanks in advance.
first, you allocate
then you "take and put" somewhere (not allocating, just copying pointers)
then you deallocate
then you deallocate. ...wait
The right way is not to use plain pointers.
The moment you start to write delete pointer;, you have to reconsider if you really need that pointer and if you do need it, if there is not some pre-packaged smart-pointer class that can take the burden of memory management from you.
The example code you posted can be written entirely without the use of pointers:
//Class A
#pragma once
#include "MyContainer.h"
#include "B.h"
class A
{
public:
A() { };
~A() { };
MyContainer<B> ListOfB;
};
//Class C
#pragma once
#include "MyContainer.h"
#include "B.h"
class C
{
public:
C() { };
~C() { };
MyContainer<B> ListOfB;
void getListOfB(MyContainer<A>& ListOfA);
};
void C::getListOfB(MyContainer<A>& ListOfA)
{
for(ListOfA.isBegin(); !ListOfA.isEnd();)
{
A& anA = ListOfA.getNext();
for(anA.ListOfB.isBegin(); !anA.ListOfB.isEnd();)
{
B aB = anA.ListOfB.getNext();
ListOfB.add(aB);
}
}
}
//Class MyContainer
#pragma once
#include <vector>
template <class T>
class MyContainer
{
public:
MyContainer(void);
~MyContainer(void) { };
T& getNext();
void removeAll();
void add(const T& t);
void isBegin();
bool isEnd();
private:
std::vector<T> items;
typename std::vector<T>::iterator it;
};
template <class T> void MyContainer<T>::add(const T& t)
{
items.push_back(t);
}
template <class T> void MyContainer<T>::removeAll()
{
items.clear();
}
template <class T>
T& MyContainer<T>::getNext()
{
if(isEnd() || isEmpty())
return throw std::out_of_range("");
return *it++;
}
template <class T>
void MyContainer<T>::isBegin()
{
it = items.begin();
}
template <class T>
bool MyContainer<T>::isEnd()
{
return it==items.end();
}
If the B instances need to be shared between class A and class C (the lists in A and C refer both to the same B objects), then you could store shared pointers in the lists.