templated placement new and destructor - c++

why that does not compile?
template <typename T>
class Pool{
char Buff[sizeof(T)*256];
public:
Pool(){
T* item = reinterpret_cast<T*>(&Buff[0]);
for(int i =0 ; i<256;i++)
item[i] = new(&item[i]) T();
}
~Pool(){
T* item = reinterpret_cast<T*>(&Buff[0]);
for(int i =0 ; i<256;i++)
item[i] -> ~ T();
}
void reset(unsigned int i){
T* item = reinterpret_cast<T*>(&Buff[0]);
item[i]->~T();
item[i]->T();
}
}
What i obviously want to achieve is calling placement new on a raw memory array (that should call constructor ok). Then I want to call destructor and constructor of items in the array. The problem is that Item is template and so if I use
Pool<FooBar>
the compiler expect to find "FooBar()" and "~FooBar()" instead of "T()" and "~T()".
is there any particular syntax to do that?
I'm using C++03 not C++11

Your syntax isn't quite right. The following should do the trick:
Pool() {
T* item = reinterpret_cast<T*>(&Buff[0]);
for(int i = 0; i < 256; i++)
new(&item[i]) T();
}
~Pool() {
T* item = reinterpret_cast<T*>(&Buff[0]);
for (int i = 0; i < 256; i++)
item[i].~T();
}
void reset(unsigned int i) {
T* item = reinterpret_cast<T*>(&Buff[0]);
item[i].~T();
new(&item[i]) T();
}

Related

Dynamic Array resizing in C++ Doesn't work properly

i have this reSize function in my Array header
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
and my main code:
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
the problem is after resizing, my values that were stored in "data" variable are gone.
when i commented the code.
//delete[] old
in the reSize function
it worked fine...so i guess the problem is when i delete the pointer it deletes also the pointer inside the struct object which i don't want it to happen..
i don't want to comment the command becuz a leak in the memory will happen...how to fix this problem ?.
Update: My Array Class .
#include <iostream>
using namespace std;
template <class T>
class Array {
private :
T* items;
int size;
int length;
public :
Array() {
this->size = 0;
items = new T[this->size];
length = 0;
}
Array(int size) {
this->size = size;
items = new T[this->size];
length = 0;
}
int getsize() {
return this->size;
}
template <class T> void push_back(T x) {
if ((length+1) <= size) {
items[length] = x;
length++;
}
else {
this->reSize(size+1);
items[length] = x;
length++;
}
}
template <class T> void Insert(int index, T x) {
if (length + 1 <= size) {
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[index] = x;
length++;
}
else {
this->reSize(size+1);
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[length] = x;
length++;
}
}
template <class T> int Find(T x) {
int index = -1;
for (int i = 0;i < length;i++) {
if (items[i] ==x) {
index = i;
break;
}
}
return index;
}
void remove(int index) {
items[index] = "";
if(index+1 < length)
for (int i = index;i < length-1;i++) {
items[i] = items[i + 1];
items[i + 1] = "";
}
length--;
}
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
void Merge(Array<T> x){
T* old = items; int oldlength = length;
items = new T[size + x.size];
size = size + x.size;
length += x.length;
for (int i = 0;i < length;i++) {
if(i< oldlength)
items[i] = old[i];
else
items[i] = x.items[i-oldlength];
}
delete[] old;
}
T& get(int index) {
return items[index];
}
}
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
// this line causes some problems
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
In your code, declaring Array<User> x(3) declares an empty array with 3 elements that are preallocated. The length property of the array is 0. When the array is copied, length(0) elements are copied over into the resized storage. When you access the 0th element, it won't be copied on resize. What you actually need to do is call push_back() to add an element to the array so that length becomes 1 and the element is copied on resize.
Also, your array class is lacking a proper copy constructor and move constructor, which means copying it won't work at all. This means that User cannot be copied properly since it contains an array, which means that resizing an array of User won't work. You need to implement a copy constructor and copy assignment operator to be able to copy the array. You also need a destructor since, right now, the array is leaking memory when it goes out of scope.

I can't add a new element to dynamic array

There is something wrong with the expand() method.
#include <iostream>
struct obj
{
int fInt;
float fFloat;
};
template <typename T>
class dynamicArray {
private:
T* myArray;
int elements;
int size;
public:
dynamicArray();
void add(T dane);
void expand();
void init(int el);
T get(int index);
};
template <typename T>
dynamicArray<T>::dynamicArray()
{
this->size = 1;
this->elements = 0;
this->myArray = new T[this->size];
init(this->elements);
}
template <typename T>
T dynamicArray<T>::get(int index)
{
return this->myArray[index];
}
template <typename T>
void dynamicArray<T>::init(int el)
{
for (size_t i = el; i < this->size; i++)
{
this->myArray[this->elements] = nullptr;
}
}
template <typename T>
void dynamicArray<T>::expand()
{
this->size *= 2;
T* tempArr = new T[this->size];
for (int i = 0; i < this->elements; i++)
{
tempArr[i] = this->myArray[i];
//tempArr[i] = new T(*this->myArray[i]);
}
for (int i = 0; i < this->elements; i++)
{
delete this->myArray[i];
}
delete this->myArray;
this->myArray = tempArr;
init(this->elements);
}
template <typename T>
void dynamicArray<T>::add(T dane)
{
if (this->size == this->elements)
this->expand();
this->myArray[this->elements] = dane;
this->elements++;
}
int main()
{
dynamicArray<obj*>* arr = new dynamicArray<obj*>();
obj* so = new obj;
so->fInt = 2;
so->fFloat = 2;
arr->add(so);
obj* so2 = new obj;
so2->fInt = 3;
so2->fFloat = 3;
arr->add(so2);
so = arr->get(0);
so2 = arr->get(1);
std::cout << so->fInt << std::endl;
std::cout << so->fInt;
}
In this for loop I would like to assign to temporary array elements of myArray but they are not the copies
for (int i = 0; i < this->elements; i++)
{
tempArr[i] = this->myArray[i];
//tempArr[i] = new T(*this->myArray[i]);
}
and when I delete them they disappear from tempArr too.
for (int i = 0; i < this->elements; i++)
{
delete this->myArray[i];
}
I tried couple things but I can't find the solution.
tempArr[i] = new T(*this->myArray[i]);
I am not sure if this is the right track, but it's giving me a
'initializing': cannot convert from 'obj' to 'T'
and
'=' cannot convert from 'T*' to 'T'
You got yourself confused, you have a pointer to an array of T, not a pointer to an array of T*, but some of your code is written as if you had the latter.
This (in expand)
for (int i = 0; i < this->elements; i++)
{
delete this->myArray[i];
}
delete this->myArray;
should simply be
delete[] this->myArray;
You can't delete individual array elements because they are not (necessarily) pointers. And delete[] this->myArray; will invoke the destructor for all elements in your array.
And init can simply be deleted, because again it assumes that your array elements are pointers.
Try writing some code with dynamicArray<int>, so that your T is definitely not a pointer. That will find all the places where you've incorrectly assumed that T is a pointer (in case I've missed any).

HEAP CORRUPTION DETECTED : after normal block ()

So, I've defined template class and then i tried to overload some operators.
template <typename T> class Set
{
public:
Set(void);
Set(Set&);
~Set(void);
bool contains(T elem);
bool add(T elem);
bool remove(T elem);
bool add(T* tab, int size);
T* getSet();
int size();
Set<T> &operator+(Set<T> &snd);
Set<T> &operator-(Set<T> &snd);
private:
T *elements;
int numOfElem;
};
When I try to add element to the Set by add method everything works fine.
template<typename T>
bool Set<T>::add(T elem)
{
bool found = false;
for(int i =0; !found && i<numOfElem; i++){
if(elem == elements[i]) found = true;
}
if( !found ){
numOfElem++;
T* tmp = new T[numOfElem];
for(int i =0; i<numOfElem-1; i++){
tmp[i] = elements[i];
}
tmp[numOfElem-1] = elem;
delete[] elements;
elements = tmp;
}
return !found;
}
template<typename T>
bool Set<T>::add(T* myArray, int size)
{
bool result = false;
for(int i =0; i<size; i++){
add(myArray[i]);
}
return result;
}
template<typename T>
Set<T>& Set<T>::operator+(Set<T> &snd)
{
Set *temp = new Set(*this);
temp->add(snd.getSet(), snd.size());
return *temp;
}
template<typename T>
void Set<T>::operator=(Set<T> &snd)
{
numOfElem = snd.numOfElem;
elements = new T[numOfElem];
for(int i =0; i < numOfElem; i++){
elements[i] = snd.elements[i];
}
}
template<typename T>
int Set<T>::size()
{
return numOfElem;
}
template<typename T>
T* Set<T>::getSet()
{
return elements;
}
template<typename T>
Set<T>::Set()
{
numOfElem = 0;
elements = nullptr;
}
template<typename T>
Set<T>::Set(Set& old)
{
numOfElem = old.numOfElem;
elements = new T(numOfElem);
for(int i = 0; i< numOfElem; i++){
elements[i] = old.elements[i];
}
}
template<typename T>
Set<T>::~Set()
{
numOfElem = 0;
delete[] elements;
elements = nullptr;
}
But if I use + operator instead (adding two separate sets) the error occurs while trying to delete the array (15 Line). Any ideas?
int main(){
Set <char> set1, set2, set3;
char tab[] = {'a','d','f','g'} ;
set1.add(tab, 4);
char tab2[] = {'a','d','x','y','z'} ;
set2.add(tab2,5);
set3= set1+set2;
}
You have a mistake in your copy constructor:
elements = new T(numOfElem);
It should be
elements = new T[numOfElem];
By writing new T(numOfElem); you allocate only one variable with its value initialized to numOfEllem.
Use a std::vector instead of the array and you will avoid such problems.
Your code is also leaking a memory in the addition operator:
template<typename T>
Set<T>& Set<T>::operator+(Set<T> &snd)
{
Set *temp = new Set(*this);
temp->add(snd.getSet(), snd.size());
return *temp;
}
You are allocating a memory and you never delete it so if you call that function too often you program may run out of its virtual memory and will crash with the uncaught std::bad_alloc exception. Change the function to this:
template<typename T>
Set<T> Set<T>::operator+(Set<T> &snd)
{
Set temp(*this);
temp.add(snd.getSet(), snd.size());
return temp;
}

Can't delete a heap instance of my custom class (C++)

Here's what I've got:
class MyClass {
int holder;
public:
MyClass() {
holder = 5;
}
};
template<class T>
class First {
std::vector<T> items;
public:
First() {
T* tmp;
for (int i = 0; i < 20; i++) {
tmp = new T();
items.push_back(*tmp);
}
};
~First() {
for (int i = 0; i < 20; i++) {
delete items.at(i);
}
};
};
class Second {
std::vector<std::deque<First<MyClass>>> items;
public:
Second() {
std::deque<First<MyClass>>* tmp;
for (int i = 0; i < 10; i++) {
tmp = new std::deque<First<MyClass>>;
items.push_back(*tmp);
}
};
~Second() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < items.at(i).size(); j++) {
delete items.at(i).at(j); // this deletes the "First" instances
}
delete items.at(i); // this deletes the deque
}
};
};
In my main, I'm create an instance of Second and adding First instances to it (through methods that aren't included). At the end of main, I delete the instance of Second, which should delete all the instances of First and the deques. However, I'm getting the following errors:
error: cannot delete expression of type 'value_type' (aka 'MyClass')
error: cannot delete expression of type 'value_type' (aka 'First<MyClass>')
error: cannot delete expression of type 'value_type' (aka 'std::deque<First<MyClass>>')
Essentially, all my delete commands are throwing errors. What am I missing here? I need to manually implement a destructor because I created a bunch of stuff on the heap - correct?
You are never storing the result of the new expression. Your code should perhaps look like this:
First() {
T* tmp;
for (int i = 0; i < 20; i++) {
tmp = new T();
items.push_back(*tmp);
delete tmp; // result of "new" is still accessible here
}
}
~First() { }
Or like this:
First() {
for (int i = 0; i < 20; i++) {
items.push_back(T());
}
}
Or just like this:
First() : items(20) {}

when doubling my stack it give me critical section error ! _ctrlvalidHeappointer

I have written a class Stack whose both sides are used, i.e. two stacks in one.
One from [0] until [someplace - 1] and one from [capacity-1] until [someplace +1].
Everything is fine but I have some problems with doubling the memory when my array is full.
My code works for doubling at first, but when it needs to double some more it gives me some weird error.
_ctrlvalidHeappointer
critical section error
This is my code. There is some explanation in the code too. When I push too many element in the stack it fails.
string firstname = "asasasasasaasasasasassasasasaasas";
string secondname= "asasdasfregeasasasasasgergergererg";
for (int i = 0; i < firstname.length(); i++)
{
a.push_at_first(firstname.at(i));
}
for (int i = 0; i < secondname.length(); i++)
{
a.push_from_end(secondname.at(i));
}
It is my class
using namespace std;
template <class T>
class Stack{
public:
Stack();
~Stack();
Stack(const Stack<T>& ob);
void double_size();
void push_at_first(T mydata);
void push_from_end(T mydata);
T & operator = (Stack<T> ob);
private:
int top;
int top2;
T * stack;
int capacity;
};
template <class T>
T& Stack<T>::operator = (Stack<T> ob)
{
if(capacity == ob.capacity){
top = ob.top;
top2 = ob.top2;
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
return *this;}
else
{
capacity = ob.capacity;
stack = new T[capacity];
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
}
}
template <class T>
Stack<T>::Stack (const Stack<T>& ob) :capacity(ob.capacity)
{
stack = new T[capacity];
top = ob.top;
top2=ob.top2;
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
}
template <class T>
Stack<T>::~Stack()
{
delete [] stack;
}
template <class T>
Stack<T>::Stack()
{
capacity = 17;
top = 0;
top2 = capacity-1;
stack = new T[capacity];
}
template <class T>
void Stack<T>::push_at_first(T mydata)
{
if ( (top + 1) == (top2 -1) ) // 1 : because I want to Be a Empty Space between Two Stack so i can tell the difference
double_size();
stack[++top] = mydata;
}
template <class T>
void Stack<T>::push_from_end(T mydata)
{
if( (top + 1) == (top2 -1) ) // 1 : because I want to Be a Empty Space between Two Stack so i can tell the difference
double_size();
stack[--top2] = mydata;
}
template <class T>
void Stack<T>::double_size()
{
Stack<T> temp(*this);
capacity *= 2;
stack = new T[capacity];
top = temp.top;
top2 = capacity - (temp.capacity - temp.top2);// capacity - number of data in stack of temp ;
// if we have something in first stack then copy 0 to top elements of temp.stack to stack
if(top > 0)
{
for (int i = 0; i <= top ; i++)
{
stack[i] = temp.stack[i];
}
}
// There is Something Wrong Down here ! i can't figure out what !
if(top2 < capacity - 1)
{
for (int i = capacity-1; i >= top2; i--)
{
stack[i] = temp.stack[i-(temp.capacity)];
}
}
}
I see several problems.
You're missing a copy constructor and assignment operator.
You're explicitly calling the destructors of the elements.
This will lead to trouble when delete does it again, as it does automatically.
You're not allocating the proper amount of memory for temp.stack in double_size. Even though you have access to the private members of temp, you should let it manage itself (see copy constructor above).
(BTW: that variable is unnecessary - just copy from your old memory block to a new one, then delete the old block and assign the new block pointer to stack.)
There may also be some problems with the indexing in double_size, but you should fix those three problems first.