Template Init-constructor error - c++

Hey I'm having trouble figuring out how to get my template header to work. I have to get my init constructor to take in an array and reverse it. So for example if I have [1,2,3,4] it takes it in [4,3,2,1]
this is my template class:
#pragma once
#include <iostream>
using namespace std;
template<typename DATA_TYPE>
class Reverser
{
private:
// Not sure to make this DATA_TYPE* or just DATA_TYPE
DATA_TYPE Data;
public:
// Init constructor
Reverser(const DATA_TYPE& input, const int & size)
{
// This is where I'm getting my error saying it's a conversion error (int* = int), not sure
// What to make Data then in the private section.
Data = new DATA_TYPE[size];
for(int i=size-1; i>=0; i--)
Data[(size-1)-i] = input[i];
}
DATA_TYPE GetReverse(){
return Data;
}
~Reverser(){
delete[] Data;
}
};
So yea if you could tell me what I'm doing wrong that'd be great.

That's because when you pass array to function it converts to pointer. You must use DATA_TYPE as pointer:
template<typename DATA_TYPE>
class Reverser
{
private:
// Not sure to make this DATA_TYPE* or just DATA_TYPE
DATA_TYPE* Data; //pointer
public:
// Init constructor
Reverser(const DATA_TYPE* input, const int & size) //pointer
{
// This is where I'm getting my error saying it's a conversion error (int* = int), not sure
// What to make Data then in the private section.
Data = new DATA_TYPE[size];
for(int i=size-1; i>=0; i--)
Data[(size-1)-i] = input[i];
}
DATA_TYPE* GetReverse(){ //Returns Pointer
return Data;
}
~Reverser(){
delete[] Data;
}
};

It seems to me like you are declaring an instance of this class with int, like
Reverser<int> myVar;
Then the Data member will be of type int. In the constructor you then try to allocate memory (with new returning a int*) and assign it to the Data member, but you can't assign a pointer to a non-pointer.
So as you write in your comment, it should be
DATA_TYPE* Data;

Related

how to allocate memory foe generic class without having a T()

I have a class and I want to write a generic sorted list that we can use it with that class:
class A
{
int n;
public:
A(int n):n(n){}
};
and this how I thought to do my sorted list class
template <class T>
class SortedList
{
T* data;
int size;
int max_size;
void expand();
static const int EXPAND_RATE=2;
static const int INITIAL_SIZE=10;
public:
SortedList();
};
template <class T>
SortedList<T>::SortedList():data(new T[INITIAL_SIZE]),size(0),max_size(INITIAL_SIZE){}
// ^^^ here we need a T()
now the problem is that class A doesn't have a c'tor like this A()
does anyone have any Idea how can I write the sortedlist class without needing the A()??
PS: some people have recommended to do Nodes with T data and next but I can't see how can I do this, and how could this help? since we still need a T()
Edit: I tried now to do it this way:
template <class T>
class SortedList
{
T** data;
// ^^
int size;
int max_size;
void expand();
static const int EXPAND_RATE=2;
static const int INITIAL_SIZE=10;
public:
SortedList();
};
template <class T>
SortedList<T>::SortedList():data(new T*[INITIAL_SIZE]),size(0),max_size(INITIAL_SIZE){}
now I am facing a different problem with this function:
void SortedList<T>::insert(const T& object)
{
if(size>=max_size)
{
expand();
}
int index=0;
for(int i=0;i<size;i++)
{
T item=*data[i];
// when I try to print item nothing goes out
if(item<object)
// ^^^ here I get a segmentation fault
{
continue;
}
index=i;
break;
}
size++;
for (int i = size-1; i >index; i--)
{
data[i]=data[i-1];
}
T Item(object);
T* ptr= &Item;
data[index]=ptr;
//when I print *data[index] it does get printed perfectly
}
does anyone have any Idea how can I write the sortedlist class without needing the A()??
Option 1: Allocate memory for each element separately. In other words, use a node based data stucture such as a linked list.
Option 2: Separate allocation of memory from creation of the object. This can be achieved by using std::allocator to allocate the memory, and std::construct_at to create the object (use placement-new instead prior to C++20). This is how dynamic array-like data structures such as std::vector are implemented.
P.S. Manual memory management is challenging. If you attempt to do it without studying the subject in depth, you'll very likely write a broken program.

Using or not using new for creation of a class in another

I have been solving a question, Dijkstra's Algorithm, in C++. I've implemented it using adjacency list.
So I have a class for a node, a class for a minHeap, and a class for the Graph.
class node
{
int vertex,weight;
node *next;
friend class Graph;
friend class minHeap;
public:
node();
node(int,int);
};
node::node(){
vertex=weight=0;
next=0;
}
node::node(int v,int wt){
vertex=v;
weight=wt;
next=0;
}
Do I define the minHeap class this way (without a friend function) and create an object in the getDijkSP() function normally, which allows me to use the object only in that function?
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap];
heapSize=-1;
pos=new int[cap]();
} //eliminating other methods
class Graph
{
node **adjList;
int v;
bool *visited;
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
}
void Graph::getDijkSP(){
minHeap hp(v); //here
hp.addElement(node(0,0));
for(int i=1;i<v;i++)
hp.addElement(node(i,INT_MAX));
while(!hp.isempty()){
node temp=hp.extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp.decreaseKey(current->vertex,current->weight+temp.weight);
}
}
(OR) Do I define the minHeap class with a friend function, so that I can create an object of the minHeap class using the new keyword? (And this helps me define the minHeap object in the scope of the Graph class, so that I can use it in all of its functions for other capabilities as well.)
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
friend class Graph; //say like this
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap]();
heapSize=-1;
pos=new int[cap]();
}
class Graph
{
node **adjList;
int v;
bool *visited;
minHeap *hp; //and do this
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
hp=new minHeap(v); //dynamic allocation
}
void Graph::getDijkSP(){
hp->addElement(node(0,0));
for(int i=1;i<v;i++)
hp->addElement(node(i,INT_MAX));
while(!hp->isempty()){
node temp=hp->extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp->decreaseKey(current->vertex,current->weight+temp.weight);
}
}
I have read this and a few other articles, but specifically want to know the advantages, disadvantages and the appropriateness of both the methods for such similar kinds of questions.
I've provided the constructors for the classes for better clarity.
Short answer would be NO. I would suggest you to read up on smart pointers and rewrite this whole mess. In C++ there is no real reason to use manual allocation in so simple project as this ever.
Also instead of assigning 0 or NULL to a pointer use nullptr, which is C++ symbol only for null pointers unlike the previous mentioned C values that are actually just a int 0 which may cause some unintentional errors.
Edit in response to your comment:
So I've decided to rewrite your code using actual modern C++ instead of this C code with simple classes. In your whole example there are almost no pointers or dynamic allocations needed. I wasn't absolutely sure who exactly should own the actual nodes so from the example I assumed that the MinHeap should. Also I didn't get the point of MinHeap::pos and Graph::visited from what I could see. I can explain any part of that code in more detail, just ask which.
Here is the code:
class Node {
// Only friend class required if you insist on keeping members of Node private.
// If they aren't meant to change, consider declaring them as public and const.
template <unsigned Size> friend class Graph;
public:
Node(int v, int wt) : vertex(v), weight(wt) {}
private:
// Default values written in here right after declarations
// There is no need for a default constructor. You never call it anyway.
int vertex;
int weight;
Node* next = nullptr;
};
// Template parameter because of internal use of std::array.
// If the capacity shouldn't be constant, use std::vector and remove template.
template <unsigned Capacity>
class MinHeap {
public:
// No constructor needed
// ---------------------
// One small tip: write parameter names in function declarations
// even if they aren't needed there for better readability of your code.
void addElement(Node n) { /* impl */ }
Node extractMin() { /* impl */ }
unsigned capacity() { return Capacity; }
bool isEmpty() { return heap.isEmpty(); }
private:
// Default values written in here right after declarations
int heapSize = -1;
std::array<Node, Capacity> heap;
};
// Template parameter because of internal use of std::array.
// If the vertex count shouldn't be constant, use std::vector and remove template.
template <unsigned Vertices>
class Graph {
public:
// No constructor needed
// ---------------------
void getDjikSP() {
hp.addElement({0, 0});
for (unsigned i = 1; i < hp.capacity(); ++i)
hp.addElement({0, INT_MAX});
while (!hp.isEmpty()) {
Node tmp = hp.extractMin();
std::cout << tmp.vertex << " " << tmp.weight << std::endl;
for (Node* current = adjList[tmp.vertex]; current != nullptr; current = current->next)
hp.decreaseKey(current->vertex, current->weight + tmp.weight);
}
}
private:
// Default values written in here right after declarations
std::array<Node*, Vertices> adjList;
MinHeap<Vertices> hp;
};
There is still a lot of space for improvements of this code, for example the MinHeaP::extractMin should maybe return Node&& if it is removed from the heap or const Node& if it should return a reference to the top, etc. To address all the problems and inefficiencies this can still have I would need to see the full code with all functions.

C++ How may I return an array class member of a nested class?

This is not a real question, since I've already solved the problem myself, but I still need some clarifications about the mechanism behind assigning an array's address to a pointer of the same type when the array is a class member of a nested class.
The following code is fully functioning, although it may lack some error_check. It is only meant to show how I made my (real) program work.
HEADER (linkedList)
class linkedList
{
public:
linkedList();
~linkedList();
int* getArray();
void forward();
private:
class listNode
{
public:
listNode();
~listNode();
friend class linkedList;
private:
int array[3];
listNode* next;
};
listNode *first;
listNode *current;
};
CPP (linkedList)
linkedList::linkedList()
{
first = new listNode;
current = first;
}
//~~~~~~~~~~~~
linkedList::~linkedList()
{
delete first;
first = 0;
current = 0;
}
//~~~~~~~~~~~~
int* linkedList::getArray()
{
if (current)
{
return &(current->array[0]);
}
}
//~~~~~~~~~~~~
void linkedList::forward()
{
if (current->next)
{
current = current->next;
}
}
//-------------------------
//-------------------------
//-------------------------
linkedList::listNode::listNode()
{
next = 0;
for (int i = 0; i < 3; i++){array[i]=((i+1)*3);}
}
//~~~~~~~~~~~~
linkedList::listNode::~listNode()
{
}
CPP (main)
#include <iostream>
#include "linked_list.h"
using namespace std;
int main()
{
linkedList list;
int *myArray;
myArray = list.getArray();
for (int i = 0; i < 3; i++){cout << myArray[i] << " ";}/**/cout << "\n\n";
return 0;
}
The real program is meant to move through a linked list made of nodes which contain 3 integer values in an array of int type, retrieve the three values and use them as parameters for some other functions.
Now, to do so I have to return the address to the first element of the array contained in the node through an accessor.
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
Why?
I've got to this solution through trial and error with very little knowlegde of the reasons that brought me to build this expression as it is.
Usually, when you want to assign the address of an array to a pointer, you just do so:
int main()
{
int array[3];
int* pArray;
pArray = array;
}
And that's it, because the name of the array itself is enough to retrieve the address of its first element.
The exact same result can be achieved by doing this (tested):
int main()
{
int array[3];
int* pArray;
pArray = &(array[0]);
}
Both methods are also valid when the accessor returns the address from a member variable of its own class.
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
What are the logic stages that make it the only viable method?
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
You aren't:
return current->array;
and
return &(current->array[0]);
Both do the same thing when the return type is int*. You aren't forced to use the second way.
Also, there's a bug in getArray. You don't return anything if current is null.
To be pedantic...
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
You're returning the address i.e. a pointer. Reference means something else.

remove a cell from array give me run time error

i have a template array consist Cells that holds the data, described in the code:
template <class T>
class Array
{
private:
//the array is consist cellss that holds the data
template<class S>
class Cell
{
public:
//members:
S* m_data;
//methods:
//C'tor:(inline)
Cell(S* data=NULL): m_data(data){};
//D'tor:(inline)
~Cell(){delete m_data;};
//C.C'tor:(inlnie)
Cell(const Cell<S>& cell): m_data(cell.m_data){};
};
private:
//members of Array:
Cell<T>* m_head,*m_last;
unsigned int m_size;
public:
/*******************C'tors and D'tors************************/
//C'tor:(inline)
Array():m_head(NULL),m_last(NULL), m_size(0){};
//D'tor:
~Array(){delete[] m_head;};
//C.C'tor:
Array(const Array& array): m_head(array.m_head),m_last(array.m_last),m_size(array.m_size){};
/****************Adding********************/
//add an element to the end of the Array:
void add(const T added);
/*******************Returning and deleting***********************/
T& operator[](const unsigned int index)const {return *(m_head[index].m_data);};
//delete the last element:
void remove();
/*********************Size*****************************/
//returning the number of elements:(inline)
const unsigned int size()const{return m_size;};
//check if the Array is empty:
bool isEmpty()const {return (m_size==0);};
};
now this is the implementaion of add:(after tests look like it works fine but just for case i write it here also)
template <class T>void Array<T>::add(const T added)
{
//allocating memory for the new array:
Cell<T>* newarray=new Cell<T>[m_size+1];
//copy all the elements from the old array:
unsigned int i;
for (i=0; i<m_size;i++)
newarray[i].m_data=m_head[i].m_data;
//put the added in the last index:
T* newelement= new T(added);
newarray[i].m_data=newelement;
//change the ptrs:
m_head=newarray;
m_last=&newarray[m_size];
//increase the counter:
m_size++;
}
and this is the implementaion of remove:
template <class T>void Array<T>::remove()
{
//if there is only 1 element:
if(m_size==1)
{
delete[] m_head;
m_head=m_last=NULL;
}
//change the last the previus cell
else
{
delete m_last;
m_last=m_last-1;
}
//and decrease the counter:
m_size--;
}
now when do:
Array<int> a;
a.add(3);//work fine
a.add(4);//work fine
a.remove();//fail
i get a runtime error from the line delete m_last; even though m_last point to a cell that actually hold data (m_last point to a cell holds 4).
what am i missing here? why cant i delete a pointer to a cell in the Array?
the error VS2012 give me:_BLOCK_TYPE_IS_VAILED(pHead->nBlockUse)
another important thing i forgot to say: when debug it doesnt enter the D'tor of Cell at all, it just get out when going to the delete.
You can't delete one element of array.
int *x = new int[10];
delete &x[2] ; // It is incorrect!
You can only delete whole of array:
delete [] x;
The destructor ~Cell calls delete. That's a sure sign that the constructor should call new.

can't delete array that is class field

I have class cAuthorisation that manages array of strAuthorisation
function resize prepares aray for next record.
During resize , on line delete [] data; I have crash.
struct strAuthorisation
{
double Amount;
}Authorisation;
class cAuthorisation {
public:
int size;
strAuthorisation *data;
cAuthorisation ()
{
size=0;
}
~cAuthorisation()
{
};
void Add(strAuthorisation )
{
resize();
data[size]=*value;
}
void resize()
{
strAuthorisation *a = new strAuthorisation[5];
size_t newSize = size + 1 ;
strAuthorisation *newArr = new strAuthorisation[newSize];
memcpy( newArr, data, size * sizeof(strAuthorisation) );
size = newSize;
delete [] data;
data = newArr;
}
} Authorisations;
Why it is not possible delete class array?
It crashes because data is an unitialised pointer. delete[] on a null pointer is safe (no-op) so initialise data in the constructor:
cAuthorisation() : size(0), data(0) {}
Note that the class as it stands is violating the rule of three.
Unsure if this is a learning exercise, if it is not use std::vector<strAuthorisation>. The std::vector will dynamically grow as required and automatically destructed when it goes out of scope.
You have not initialized the data pointer. So you are making something like this:
Foo *data;
delete [] data;
"data" is a pointer who's value was never initialized.