build success but run fail for Stack class - c++

So, I am trying to run the class below with
int x = 5;
mystack<int> st;
st.push(x);
However, I keep getting build failure, I can't seem to figure out why.
#ifndef MYSTACK_H
#define MYSTACK_H
#include <vector>
using namespace std;
template<typename T>
class mystack {
private:
vector<T> data;
int size = 0;
public:
void push(T const &);
};
template<typename T>
void mystack<T>::push(T const & elem) {
data[size] = elem;
size++;
}
RUN FAILED ( exit value -1, 073, 741, 819, total time: 1s)
Also completely separate question, how do I throw an underflow? I tried
throw underflow_error();

Initially your vector<T> data is empty. Its size() is 0. You cannot access to any of its elements. That might be the reason of getting an error.
Try using this code:
template<typename T>
void mystack<T>::push(T const & elem) {
data.push_back(elem);
}
It actually will increase you data.size() by 1 every time you push an element.
Don't want to use any vector STL
Wonder you are having vector<T> in code, looks like STL. You can use plain dynamic arrays as an alternative or even static ones.
template<typename T>
class mystack {
private:
T* data;
int size = 0;
int maxSize;
public:
mystack(int maxSize) :maxSize(maxSize) { data = new data[maxSize]; }
~mystack() { delete[] data; }
void push(T const &);
};
template<typename T>
void mystack<T>::push(T const & elem) {
// here you may check if you already reached the maxSize;
data[size++] = elem;
}
Note that in order to fully simulate STL vector behaviour you should consider reallocating the array each time you have size = allocateSize. STL vector makes this every time the number of elements hits the power of 2, it doubles its size.

I propose you to use std::stack instead of implement your own stack using std::vector. If you don't want use STL at all, your should control memory allocation and deletion by yourself. In your example, in the line data[size] = elem;, you assign value to not allocated memory, it is your problem. You can fix it that way, if you don't want to use push_back() method:
template<typename T>
void mystack<T>::push(T const & elem) {
size += 1;
data.resize(size);
data[size] = elem;
}
About std::underflow_error. It designed for arithmetic underflow errors. Anyway, this class has constructor where your should put string, so you need change throw underflow_error(); to throw underflow_error("Error message");.

Related

Runtime error while implementing vector in c++

I am trying to implement my own version of vector in c++.
So far I have done this..
#include<iostream>
#include<string>
using namespace std;
template<class T>
class vec
{
public:
T *a;
int i,N;
vec(int N=0):N(N)
{
i=-1;
a=(T *)malloc(N*sizeof(T));
}
void push_back(const T& t);
T at(const int& index) const;
};
template<class T>
void vec<T>::push_back(const T& t)
{
if(++i==N)
{
a=(T *)realloc(a,(++N)*sizeof(T));
}
a[i]=t;
}
template<class T>
T vec<T>::at(const int& index) const
{
return a[index];
}
int main()
{
vec<string> v;
v.push_back("2");
v.push_back("1");
v.push_back("3");
cout<<v.at(0)<<endl;
return 0;
}
But I am getting a run time error when I run this
Where is the error in the above code?
I am using c++ and visual studio to run.
In this case you need to use placement new.
something like this:
// Allocate memory
void* mem = malloc(sizeof(std::string));
// Call constructor via placement new on already allocated memory
std::string* ptr = new (mem) std::string();
But then, you are forced to explicitly call destructor for this memory
ptr->~std::string();
Overall - this is not really good way to achieve what you want. It's more convenient to use usual new\delete operators and copy internal data on re-allocation (how it was done in STL vector)

Deleting a member array of pointers, then reallocating it

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;

End of array points to newly allocated array C++

Using C++, I am trying to create an array that holds pointers to objects I'm storing. But when the array is full, I want to expand the array.
the easy option is to allocate a new array with bigger size, then copy the elements to it, this is quite inefficient, and I thought of another way I want to try to do it:
create array of fixed size X
When full, create a new array, and make the end of the first array point to the start of the first element
Repeat as long as needed
What methods can I use to do that? I thought of one way to do it, but it seems very hacky:
declare all my new array as pointers to object pointer, then reinterprit_cast the filled elements to object pointer.
Note: I know I can use Vector, but I am instructed not to use std library.
Kind Regards,
There are some good answers in the comments already. I just want to provide a way to achieve exactly the behavior you described.
Since the elements of the array are pointers as well, you can define a union as the element of your array like this:
template<typename T>
union Cell
{
T* pElm;
Cell* pNext;//A fixed size array of Cells
}
And then build your array on top of it. For example:
template<typename T>
class SpecialArray
{
public:
//the next pointer is included
static const size_t ARRAY_LEN = 1000;// For example
using Pointer = T*;
using Segment = Cell<T>[ARRAY_LEN];
protected:
Segment* pFirst;
size_t mSize;
public:
SpecialArray()
:pFirst(nullptr),mSize(0){}
SpecialArray(SpecialArray&&){}
~SpecialArray(){}
Pointer& operator[](size_t index)
{
Segment* seg = pFirst;
size_t offest = 0;
//Search logic...
return seg[offest]->pElm;
}
const Pointer& operator[](size_t index) const;
};
Using C++, I am trying to create an array that holds pointers to
objects I'm storing. But when the array is full, I want to expand the
array.
With C++ templates and C primitives we can improvise a simple vector like below. And the grow buffer strategy is to double the size when the threshold is met.
#include <iostream>
#include <stdlib.h>
template <typename T>
class MyVector
{
public:
MyVector() : m_count(0), m_size(0), m_buffer(0)
{
m_size = bufInitSize;
m_buffer = (T*)malloc(sizeof(T) * bufInitSize);
}
~MyVector()
{
if (m_buffer)
free(m_buffer);
}
void add(const T& p)
{
if (m_count + 1 >= m_size)
{
m_size *= 2;
m_buffer = (T*)realloc(m_buffer, sizeof(T) * m_size);
}
m_buffer[m_count ++ ] = p;
}
T& operator[](int idx)
{
return m_buffer[idx];
}
private:
static const int bufInitSize = 1024;
T* m_buffer;
int m_count;
int m_size;
};
void main()
{
// using MyVector
MyVector<int*> vctOfIntPtr;
int n = 100;
vctOfIntPtr.add(&n);
int* pN = vctOfIntPtr[0];
std::cout << *pN;
}

How do you create a template definition for a fixed-size array class in C++?

I need to create a template because I don't know what it's an array of. And it needs to be of the size that's passed in the constructor. So here is what I got and I got all sorts of errors. I am a beginner to C++ so any help is appreciated :)
template <typename T, int N>
class Array
{
public:
T& operator[](int index)
{
return data[index];
}
private:
int size;
T *data[N];
};
I think you understand what I'm trying to do. I also need to overload the subscript operator, as you can see. Not sure if I need a reference or a pointer or what. I did have a constructor but it wasn't working properly.
Here's a corrected version with a sample main as well:
#include <iostream>
using namespace std;
template <typename T, int N>
class Array
{
public:
T& operator[](int index)
{
// add check for array index out of bounds i.e. access within 0 to N-1
return data[index];
}
Array() {
data = new T[size = N];
}
~Array() {
if (data)
delete [] data;
}
private:
int size;
T *data;
};
int main(void) {
Array<int, 4> a;
a[0] = 5;
cout << a[0] << endl;
return 0;
}
From what I can see your template is containing an array of pointers, which from what I read and from your [] operator implementation is not what you intend to do. So first you should remove the * from :
T *data[N];
You should probably initialize the size of your template from your constructor, thus you should change :
T *data[N];
to :
T* data;
and :
template <typename T, int N>
to :
template<typename T>
Now that changes the implementation a bit, you should now write a constructor like that :
template<typename T>
Array(int n) {
data = new T[n];
}
and now you should also add a destructor like that :
~Array() {
delete[] data;
}
and there you go :)
However if you want to keep the size as an argument of the template your constructor go like :
template<typename T, int N>
Array() {
}
and the declaration of data :
T data[N];
As said in comments, you may want to use std::array in "real life" conditions, but as a training, implementing your own Array is a good thing to do, that's a training most computer schools do after all.

Initialising nested templates

I'm trying to learn more about templates and have come across a problem I can't seem to solve. At the moment the class below works fine.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
template <class T, int s>
class myArray{
public:
T* data;
inline T& operator[](const int i){return data[i];}
myArray(){
data=new T[s];
}
myArray(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArray& operator=(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
return *this;
}
~myArray(){delete [] data;}
};
If I use it:
myArray<myArray<myArray<int,10>,20>,30> a;
a is now 30x20x10 array that I can access with the normal array brackets e.g. a[5][5][5]. I wish to add a feature so that I could write:
myArray<myArray<myArray<int,10>,20>,30> a(10);
and initialise all of the entries to 10 for example. I can't work out how to do this. As I understand, each layer of myArray is constructed using the default constructor. If I changed this to something like:
myArray(int n=0){
data=new T[s];
fill(data,data+s,n); //T might not be of type int so this could fail.
}
I think this should fail when data is not of type int (i.e. on any array on dimensions > 1), however it doesn't. It works when the array is square, but if not then some of the entries aren't set to 10. Does anyone have an idea how the standard vectors class achieves this? Any help would be amazing. Thanks!
Well, try something like this:
myArray()
: data(new T[s]()) // value-initialization!
{
}
myArray(T const & val)
: data(new T[s]) // default-initialization suffices
{
std::fill(data, data + s, val);
}
If you're into variadic templates, you might cook up something even more grotesque involving variadically filled initializer lists, but I think we've done enough learning for one week.
Note the fundamental flaw in using new: Either version requires that your class T can be instantiated in some "default" state, and that it be assignable, even though we never require the default state in the second version. That's why "real" libraries separate memory allocation and object construction, and you never see a new expression unless its the placement version.
std::vector uses placement new on memory blocks. It constructs the data.after allocating the memory in a second line of code.
This technique would work for you as well. Be careful with placement new as it requires you to call destructors manually as well.
Here is a half-assed route without placement new:
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
AllocateSpace(N); // write this, just allocates space
for (int i = 0; i < N; ++i)
{
Element(i) = T( constructFromAnythingElse );
}
}
with placement new, you have to allocate the memory first, then construct in-place, and then remember to destroy each element at the end.
The above is half-assed compared to a placement new route, because we first construct each element, then build another one, and use operator= to overwrite it.
By making it a template constructor on an arbitrary type, we don't rely on multiple conversion to get multiple levels down into the array. The naive version (where you take a T const&) doesn't work because to construct an array of arrays of arrays of T, the outermost one expects an array of arrays of T as an argument, which expects an array of T as an argument, which expects a T -- there are too many levels of user defined construction going on there.
With the above template constructor, the array of array of array of T accepts any type as a constructor. As does the array of array of T, as does the array of T. Finally, the T is passed in whatever you constructed the outermost array of array of array of T, and if it doesn't like it, you get a compiler error message that is nearly completely unreadable.
Make specialization for arrays containing other arrays. To do this you need some common implementation class to be used in general and specialized MyArray:
Common implementation (I made some fixes for you - see !!! comments):
template <class T, int s>
class myArrayImpl {
public:
T* data;
T& operator[](int i){return data[i];} //!!! const before int not needed
const T& operator[](int i) const {return data[i];} //!!! was missing
myArrayImpl(){
data=new T[s]();
}
myArrayImpl(const myArrayImpl & other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArrayImpl& operator=(const myArrayImpl& other){
T* olddata = data; // !!! need to store old data
data=new T[s];
copy(other.data,other.data+s,data);
delete [] olddata; //!!! to delete it after copying
return *this;
}
~myArrayImpl(){delete [] data;}
};
Then make general implementation - note the definition of value_type and setAll:
template <class T, int s>
class myArray : private myArrayImpl<T,s> {
typedef myArrayImpl<T,s> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef T value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
fill(this->data, this->data + s, value);
}
};
And the specialized version for myArray of myArray - see also differences in value_type and setAll:
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef typename myArray<T,s2>::value_type value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
}
};
And usage:
int main() {
myArray<myArray<myArray<int,7>,8>,9> a(7);
std::cout << a[0][0][0] << std::endl;
std::cout << a[8][7][6] << std::endl;
}
Full example here: http://ideone.com/0wdT9D