I have this class for double linked lists:
template <typename T>
class Akeraios
{
struct node
{
T data;
node* prev;
node* next;
node(T t, node* p, node* n) : data(t), prev(p), next(n) {}
};
node* head;
node* tail;
public:
Akeraios() : head( NULL ), tail ( NULL ) {}
template<int N>
Akeraios( T (&arr) [N]) : head( NULL ), tail ( NULL ) //meta apo : simainei einai initializer list--arxikopoiisi listas
{
for( int i(0); i != N; ++i)
push_back(arr[i]);
}
bool empty() const { return ( !head || !tail ); }
operator bool() const { return !empty(); }
void push_back(T);
void push_front(T);
T pop_back();
T pop_front();
~Akeraios()
{
while(head)
{
node* temp(head);
head=head->next;
delete temp;
}
}
};
and somewhere in main
int arr[num1len];
int i=1;
Akeraios <int> dlist ( arr );//error line!!
for(i=1;i<=num1len;i++){
double digit;
int div=10;
int j;
for(j=1;j<=i;j++)div=div*div;
digit=number1/div;
int dig=(int) digit;
the error in error line is:
no matching function for call to `Akeraios::Akeraios(int[((unsigned int)((int)num1len))])'
candidates are: Akeraios::Akeraios(const Akeraios&)
note Akeraios::Akeraios() [with T = int]
try this:
Akeraios <int>* dlist = new Akeraios( arr );
your compiler thinks you're calling a function doing it the way you do it.
you could also use the implicit constructor
Akeraios<int> dlist = arr;
(not very nice this is)
This code is perfectly valid and compliant as-is. The only way I can see it messing up is if you had a compiler extension for VLAs and attempted to call the constructor with a variable-length array, which would almost certainly fail. Otherwise, it is perfectly legitimate. Visual Studio accepts without quarrel.
Since you're saying that num1len is a variable:
Templates are evaluated at compile-time. When you say arr[num1len], you're specifying an array with a variable length (is this C99 or something?). The template expects an array with a size that can be evaluated at compile time (you're saying template<int N>Akeraios( T (&arr) [N]), so there's no way the compiler can match that up.
Just imagine you had a specialization for N=5 or N=10. How would the compiler be able to find the right specialization when compiling the code if the size of the array is not known at that point?
Related
I have my own classes which implements queue and stack using LL, the source code compiles fine on my machine but after throwing it in valgrind it shows me some memory leaks
class S{
private:
struct Node{
int value;
Node* next;
Node(int v, Node* n):value(v), next(n){}
};
Node* head;
S(const S& other) {}
S& operator=(const S& other) {}
public:
S():head(NULL){}
void push(unsigned int data){
head = new Node(data, head);
}
class Q{
private:
struct Node{
int value;
Node* next;
Node(int v, Node* n):value(v), next(n){}
};
Node* head;
Node* tail;
int size;
Q(const Q& other) {}
Q& operator=(const Q& other) {}
public:
Q():head(NULL), tail(NULL), size(0){}
void push(int data){
if (head == NULL) head = tail = new Node(data, tail);
else{
tail -> next = new Node(data, tail);
tail = new Node(data, tail);
}
size++;
}
What am i doing wrong? Much help would be appreciated :) cheers
In your class constructor:
PQ(int cap){
capacity = cap;
arr = new int [capacity++];
for (int i= 0; i < capacity; i++) arr[i] = {0};}
this:
capacity++
will first return the capacity and then increase its value by one.
Because of this, when you are filling your array in a for loop, you are going out of array range, because your array size is 1 less than the capacity value.
This is not a "memory leak".
This is memory corruption. You can start fixing it by making a mental effort to understand that arrays in C++ are 0-based, not 1-based. The first element of an array is array[0] and not array[1], and everything else is based on that. The following is based on the notion that array elements start with array element #1:
int top(){
return arr[1];
}
void pop(){
arr[1] = arr[size];
The first element of an array is element #0, not element #1, but this is structured based on the concept that the first element in the array is element #1.
It might seem like adding 1 to the array size before allocating it is an easy way to avoid having to make this adjustment, but it only leads to more grief, confusion, and bugs, later down the line. This is why, apparently, the constructor attempts to increment the size of the array before allocating it:
PQ(int cap){
capacity = cap;
arr = new int [capacity++];
for (int i= 0; i < capacity; i++) arr[i] = {0};
}
Except that it increments it incorrectly. It's a post-increment, so if, for example, cap was 4, new int[4] gets allocated, before capacity gets incremented. The next line attempts to clear array elements #0 through #4, except that array element #4 doesn't exist, the code tries to initialize it, runs off the end of the array, and valgrind throws a red flag.
Although this is fixable simply by using pre-increment instead of post-increment, the correct solution is not to increment at all, but restructure the code so that it follows the natural properties of C++ arrays being 0-based, instead of 1-based.
Here's my attempt at creating a simple constexpr linked list -
struct Node
{
constexpr Node(const int n, Node const* next = nullptr)
: value(n), next(next) {}
constexpr Node push(const int n) const { return Node(n, this); }
int value;
Node const* next;
};
constexpr auto getSum(Node n) {
int sum = 0;
Node *current = &n;
while(current != nullptr) {
sum += current->value;
current = current->next;
}
return sum;
}
int main() {
constexpr Node a(0);
a.push(1);
a.push(22);
constexpr auto result = getSum(a);
return result;
}
on compiling this program, the following error is shown
prog.cc: In function 'constexpr auto getSum(Node)':
prog.cc:16:28: error: invalid conversion from 'const Node*' to 'Node*' [-fpermissive]
current = current->next;
~~~~~~~~~^~~~
prog.cc: In function 'int main()':
prog.cc:25:35: in constexpr expansion of 'getSum(a)'
prog.cc:16:28: error: conversion of 'const Node*' null pointer to 'Node*' is not a constant expression
How should I proceed forward to solve this issue and generate such linked list? Here is Wandbox Link for seeing the execution online.
The immediate error is straightforward to fix:
Node const *current = &n;
// ^^^^^
The complaint is that current = current->next; is assigning a Node const* to a Node *, so don't do that.
Doing that will make your program compile but print 0, because neither push calls modified a. You also can't store the result of push as constexpr since the address of a, an automatic local variable, isn't a constant expression.
You can, however, form a linked list of temporary nodes and immediately use it:
constexpr auto result = getSum(a.push(1).push(22).push(19)); // OK, 42
As #hg_git pointed out in the commentary of your post, a constexpr linked list is not possible.
I cleaned up your code to have a useful error.
#include <iostream>
struct Node
{
constexpr Node(const int n, Node * next = nullptr)
: value(n), next(next) {}
constexpr Node push(const int n) { return Node(n, this); }
int value;
Node * next;
};
constexpr auto getSum(Node n) {
int sum = 0;
Node *current = &n;
while(current != nullptr) {
sum += current->value;
current = current->next;
}
return sum;
}
int main() {
constexpr Node a(0);
a.push(1);
a.push(22);
constexpr auto result = getSum(a);
return result;
}
Giving this
main.cpp: In function 'int main()':
main.cpp:25:13: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive]
a.push(1);
^
main.cpp:7:20: note: in call to 'constexpr Node Node::push(int)'
constexpr Node push(const int n) { return Node(n, this); }
^~~~
main.cpp:26:14: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive]
a.push(22);
^
main.cpp:7:20: note: in call to 'constexpr Node Node::push(int)'
constexpr Node push(const int n) { return Node(n, this); }
As you can see, even if the keyword const is not there, there is still some problems with const parameters. This comes from the fact that constexpr are calculated at compilation time. Thus making them immutable at run time.
A linked list could change at runtime; if you add or remove a Node per example.
So constexpr are not the right choice in this case.
Edit :
Here's a live demo of your code, clean from constexpr. I added some commentary, feel free to ask if you don't understand a line or a function.
I'm creating a stack class as an exercise trying to learn some c++ concepts (initializer lists, memory management and templates here). I've run into something that I can't get my head around.
In function void Stack::push(const T& item), if I uncomment the delete [] data; line, my code runs well when the template argument is for example int or char. But with std::string, I get weird memory errors.
My thinking here is that I need a bigger array -> arrays can't be resized -> I create a new one -> I deallocate the memory I needed for the one that's soon to be not needed -> I make the existing pointer point to a new memory address where I create the bigger array.
Now, when I comment the delete line, the code runs well even with std::string, but I can't see why I can't do the delete operation safely with all types.
Any insights will be appreciated.
#include <iostream>
#include <stdio.h>
#include <memory.h>
template<class T>
class Stack
{
T* data;
int sz;
public:
//Stack(){sz=0;}
Stack(const std::initializer_list<T>&);
~Stack();
void push(const T&);
T& pop();
void show() const;
};
template<class T>
Stack<T>::Stack(const std::initializer_list<T> &list)
{
sz=0;
data = new T[list.size()];
for (auto i : list) {
data[sz] = i;
++sz;
}
std::cout<< "Created with sz: "<< sz<<std::endl;
}
template<class T>
Stack<T>::~Stack()
{
delete [] data;
}
template<class T>
void Stack<T>::push(const T& item) {
std::cout<<"push "<<item<<std::endl;
T* arr = new T[sz];
memcpy(arr, data, sz*sizeof(T));
//delete [] data;
data = new T[sz + 1];
memcpy(data, arr, sz*sizeof(T));
++sz;
data[sz - 1] = item;
std::cout<<"new size: "<<sz<<", bytes: "<<sz*sizeof(T)<<std::endl;
}
template<class T>
T& Stack<T>::pop()
{
if(sz > 0) {
std::cout<<"pop "<<data[sz-1]<<std::endl;
std::cout<<"new size: "<<sz-1<<std::endl;
return data[--sz];
}
else
return data[0];
}
template<class T>
void Stack<T>::show() const
{
for (int i=0; i<sz; i++) {
std::cout<<data[i]<<" ";
}
std::cout<<std::endl;
}
int main(){
Stack<int> s = {1,2,3,4,5,6,7,8,9,10,11};
s.show();
s.push(12);
s.push(13);
s.push(14);
s.pop();
s.pop();
s.push(15);
s.push(16);
s.show();
Stack<std::string> d = {"one","two","three"};
d.show();
d.pop();
d.push("four");
d.show();
return 0;
}
Don't use memcpy to copy objects, that will copy the bits alright, but for some object a bit-wise copy is not correct as the copy constructor (or copy assignment operator) Will not be used.
A good and simple example is if you have a stack of std::string objects. When you do a bit-wise copy (with memcpy) the contents of the std::string objects are copied, but that basically is just a pointer and a size. When you do a bit-wise copy then you will have two std::string objects referencing the same memory. Destroying one of those object will lead to the other having a stray pointer to some memory (that used to contain the string) that no longer is owned by your program.
To solve this use std::copy instead to copy the objects, it will do the right thing.
Unrelated to your problem, but your push function does a copy that it doesn't need:
T* arr = new T[sz];
memcpy(arr, data, sz*sizeof(T));
This is simply not needed, instead do something like
T* oldData = data;
data = new T[sz + 1];
// Copy from old array to new
std::copy(oldData, oldData + sz, data);
delete[] oldData;
I am trying create my own vector, I am at the beginning, and when compile e execute the code, i get "Program not responding". This is the code:
struct X
{
X(){};
~X(){};
int v1, v2, v3;
};
template<typename T>
class Vector
{
public:
// constructors
Vector();
Vector(unsigned s);
virtual ~Vector();
// overloaded operators
T operator[](unsigned index);
// others
void clear();
void add(T value);
unsigned getSize();
bool isEmpty();
private:
// pointer to first item of memory block
T* first;
unsigned size;
};
template<typename T>
Vector<T>::Vector()
{
first = NULL;
size = 0;
}
template<typename T>
Vector<T>::Vector(unsigned s)
{
size = s;
first = new T[s];
};
template<typename T>
Vector<T>::~Vector()
{
clear();
}
template<typename T>
void Vector<T>::clear()
{
for(unsigned i = size ; i > 0 ; i--)
delete &first[i];
first = NULL;
}
template<typename T>
void Vector<T>::add(T value)
{
T* temp = new T[size + 1]; // error happens here
// copy data to new location
for(unsigned i = 0 ; i < size ; i++)
temp[i] = first[i];
// delete older data
clear();
// add the new value in last index
temp[size + 1] = value;
// update the pointer
first = temp;
size++;
}
template<typename T>
T Vector<T>::operator[](unsigned index)
{
return first[index];
}
template<typename T>
unsigned Vector<T>::getSize()
{
return size;
}
template<typename T>
bool Vector<T>::isEmpty()
{
return first == NULL;
}
int main(int argc, char* args[])
{
Vector<X> anything;
X thing;
anything.add(thing);
anything.add(thing);
anything.add(thing); // if remove this line, program work fine.
}
As I commented, error happens in T* temp = new T[size + 1];.
If i define the value of v1, v2, v3 of X class, e.g. X() : v1(0), v2(0), v3(0) { }, the program works correctly.
If i change the type, e.g., Vector of int, he works perfectly.
If put X class in std::vector, work fine too.
Other comments are also accepted.
Can someone helpme?
Your description of the problem is incredibly vague, but I can point out problems with your code:
No vector copy constructor (causes double-deletes and crashes)
No vector copy assignment (causes double-deletes and crashes)
clear is incorrectly calling delete (causes crashes and corruption) (you should match your single new of an array with a single delete of the array. Don't loop over elements.
add is writing past the end of the array (causes crashes and corruption)
add is not exception safe
You have to fix at least the first four. The third and fourth are probably the causes of your hang.
You have a buffer overflow occurring.
T* temp = new T[size + 1]; // When size is 0, you allocate 1 space.
You then assign to the temp array, but in location temp[1], which isn't a valid location because your array has only 1 element. This is undefined behavior, and that this point, your program is free to continue however it chooses. In this case, it seems to loop indefinitely.
// add the new value in last index
temp[size + 1] = value; // When size is zero, your array is length '1', but
// you are accessing temp[1] which is outside the
// bounds of your allocated memory.
I'm wondering how I would go about storing a value into a struct that is part of a linked list of structs. I have:
struct polynomial
{
polynomial(string newCoefficient, string newPower, polynomial *nextPtr);
string coefficient;
string power;
polynomial *next;
};
class linkedList
{
public:
void createList();
private:
polynomial *head;
};
For this assignment, we need to do some parsing when gathering input values. For example, we are to input two numbers separated by a space (ex. 7 9 or 10 8). Therefore, in void createList(), I want to read in a line using string, convert it to a char array to strip down the values, then store that value into polynomial.coefficient and polynomial.power, for each node in the linked list.
Or, I was searching some information up, and I was thinking maybe I can input two int values and then use stringstream to convert them into strings and them store into coefficient and power.
Either way, can you help introduce me to the concept of storing a value into a linked listed struct?
EDIT: I have added the overloaded constructor:
polynomial:: polynomial ( string newCoefficient, string newPower, polynomial *nextPtr )
{
coefficient = newCoefficient;
power = newPower;
next = nextPtr;
};
You are mixing C-style practice with C++ practice.
In C++, you generally separate the data from the container. Look at how std::list works.
Even if you don't want to get into templating, you can still do this:
struct polynomial {
string coefficient;
string power;
};
struct listnode {
polynomial data;
listnode *next;
};
If you really want to have the head concept, you can either keep a 'dummy head' where you store one listnode that has nothing in it.
Alternatively, if you really want the next pointer in polynomial and you want a way to copy over an existing element without nuking the pointer, just make a setter function:
void polynomial::set( const string& inCoeff, const string & inPower );
I tested the following code which may help you out:
struct Polynomial {
string coefficient;
string power;
Polynomial* next;
Polynomial(const string& coeff, const string& pow) : coefficient(coeff), power(pow), next(NULL) {}
};
// linked-list of Polynomials
struct LinkedList {
Polynomial* head;
LinkedList() : head(NULL) {}
// add to end of list
void add(const string& coeff, const string& pow) {
if(head == NULL)
head = new Polynomial(coeff, pow);
else {
Polynomial* n;
for(n = head; n->next != NULL; n = n->next);
n->next = new Polynomial(coeff, pow);
}
}
// check if results are correct
void print() {
for(Polynomial* n = head; n != NULL; n = n->next)
cout << n->coefficient << " " << n->power << endl;
}
};
// somewhere in main()
LinkedList ll;
...
// read input values
ll.add(coeff1, pow1);
ll.add(coeff2, pow2);
ll.add(coeff3, pow3);
// check results
ll.print();
Note your Polynomial struct members need not be strings. Instead you could just parse your input and store cofficient as float and power as int (All polynomial exponents are integers).