Double pointer doesn't call object constructor when using new - c++

My problem seems to be answered with only single pointers. I'm trying to dynamically allocate for a 2d linked list. The problem I ran into when I'm trying to use class llist constructor to set head and tail pointer to NULL :
//I've included only the parts that I see are neccesary
struct node {
int value ;
int weight ;
node* next ;
} ;
class llist{
private :
node* tail, *head ;
public :
llist(){tail = NULL ; head = NULL ;} /* this unneccesary retype is to make sure
that it wasn't a typo*/
}
class list_graph
{
private :
int size, s;
llist ** v ;
public :
list_graph(int s){
this -> s = s ;
size = 0 ;
v = new llist* [s] ;
}
}
I've use the debugger and ran through every steps and it seems that my constructor for llist is not called after I create a object of list_graph type, so every other function that relies on this fails and gives me segmentation fault. Is there anything I'm doing wrong, or is there any workarounds beside using the STL list, many thanks

This:
v = new llist* [s] ;
creates an array of pointers to type llist, but it doesn't create any llist objects. If you want an array of such things, then you want:
llist * v ;
and:
v = new llist[s] ;
Or better still, if this is not a homework assignment, use std::vector. And don't think of things like llist ** v as "double pointers"; think of them as what they are - pointers to pointers.

If you want to allocate a 2D pointer array, you can do it a couple ways:
Using a dynamic array of pointer arrays, given some width and height:
llist** data = new llist*[width];
for (int i = 0; i < width; ++i){
data[i] = new llist[height]; // constructors get called here
}
// accessing a linked list, make sure x is in [0, width) and y is in [0, height):
data[x][y]->value;
Using a single pointer array:
llist* data = new llist[width * height]; // constructors get called here
// accessing a linked list:
// again, make sure x is in [0, width) and y is in [0, height)
data[x + (y * width)]->value;

If you want to keep v as a array of pointers to llist objects, as opposed to an array of llist objects (suggested by Neil Butterworth), dynamically allocate each pointer by changing your list_graph constructor to
list_graph(int s) : size(0), s(s), v(new llist* [s]) {
for (int i(0); i < s; ++i)
v[i] = new llist();
}
EDIT: To avoid calling new s times in the for loop, you could pre-allocate all s llist objects at once. However, this would mean they can not be deleted individually. Your class would look like
class list_graph {
int size, s;
llist* buffer;
llist ** v ;
public:
list_graph(int s) : size(0), s(s),
buffer(new llist[s]), v(new llist* [s]) {
for (int i(0); i < s; ++i)
v[i] = &buffer[i];
}
~list_graph() {
delete[] v;
delete[] buffer;
}
};

Related

C++ destructor throws error

I have the following code:
class MyList
{
private:
public:
int* list;
int size = 0;
int max;
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
};
// destructor
~MyList()
{
for (int x = 0; x < max; x++)
delete (list + x);
};
};
I tried to clear the memory with that destructor. However, it throws an error on second iteration. What did I do wrong? Also, it wouldn't let me do it this way:
delete list[x];
Can someone explain to me why? Thank you so much.
You should use delete[] because list is created via new[]-expression. e.g.
// destructor
~MyList()
{
delete[] list;
}
Note that they must be pair; new int[max] create an array containing max's elements, delete[] destroy the whole array. delete should only be used for pointer created by new.
And better to change the constructor to
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
else
list = nullptr;
}
to make sure list is always valid.
Try this:
MyList(int s)
: max(s),
size(0),
list(new int[s])
{
};
~MyList()
{
delete[] list;
};
i dnt understand why are you using
a loop to deallocate that memory.... you should simpy write
delete[] list;
that would be enough!
in your destructor you are using delete (list(a pointer)+x) this is not deallocating memory you created...
you are tryin to delete addresses next to your list by adding value of x loop in it
i hope you understood your error :)

A shared pointer query from a novice user. I have code below that crashes when using a container of class with member shared pointers

//this is my main Method ,this was an experiment to understand shared pointer usage
#include <iostream>
#include "shared_ptrtestA.h"
int main(int argc, const char * argv[]) {
// declare a shared pointer to the class
sharedptr_testA* A = new sharedptr_testA(5);
//class has a vector , push back a new instance into the vector
A->mvect.push_back(sharedptr_testA::Aptr(new sharedptr_testA::testA(
sharedptr_testA::sharedptr_testB::Create(1) , sharedptr_testA::sharedptr_testC::Create(1)
)));
//class has a vector , push back a new instance into the vector
A->mvect.push_back(sharedptr_testA::Aptr(new sharedptr_testA::testA(
sharedptr_testA::sharedptr_testB::Create(2),sharedptr_testA::sharedptr_testC::Create(2)
)));
//iterate the vector populated above
for(std::vector<sharedptr_testA::Aptr>::iterator it = A->mvect.begin() ;
it!= A->mvect.end() ; it++)
{
// get members from the vector iterator
sharedptr_testA:: sharedptr_testB::Bptr B = (*it)->mb;
sharedptr_testA:: sharedptr_testC::Cptr C = (*it)->mc;
// print contents of members
for(int i = 0 ; i < B->m_size ; i++)
{
std::cout<<B->bytes[i]<<'\t';
}
std::cout <<std::endl;
for(int i = 0 ; i < C->m_size ; i++)
{
std::cout<<C->bytes[i]<<'\t';
}
std::cout <<std::endl;
}
}
//this was the main method above and the expected output was
B
C
BB
CC
The structure of the classes used are
//Header File
#ifndef shared_ptrtest_shared_ptrtestA_h
#define shared_ptrtest_shared_ptrtestA_h
#include <memory>
#include <functional>
#include <vector>
class sharedptr_testA
{
public:
// constructor and destructor
sharedptr_testA(int vsize);
~sharedptr_testA();
// an internal class member defined
class sharedptr_testB
{
public:
typedef std::shared_ptr<sharedptr_testB> Bptr;
//static create method
static Bptr Create(int msize)
{
return Bptr(new sharedptr_testB(msize));
}
//members
int m_size;
char *bytes;
//private contructor
private:
sharedptr_testB(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[size]= 'B';
}
};
//class c has same structure as class B above
class sharedptr_testC
{
public:
typedef std::shared_ptr<sharedptr_testC> Cptr;
static Cptr Create(int msize)
{
return Cptr(new sharedptr_testC(msize));
}
int m_size;
char *bytes;
private:
sharedptr_testC(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[size]= 'C';
}
};
// struct containing shared pointers to classes defined above
struct testA
{
testA(sharedptr_testB::Bptr B, sharedptr_testC::Cptr C)
{
mb = B;
mc = C;
}
sharedptr_testB::Bptr mb;
sharedptr_testC::Cptr mc;
};
typedef std::shared_ptr<testA> Aptr;
std::vector<Aptr> mvect;
};
#endif
//The short cpp file for the above class contains only constructor and destructor
#include "shared_ptrtestA.h"
sharedptr_testA::sharedptr_testA(int vsize)
:mvect(vsize)
{
}
sharedptr_testA::~sharedptr_testA()
{
}
What is wrong in the above code ? I wrote this to understand shared pointer usage
You have two bugs in your program:
The loops in constructors of sharedptr_testB and sharedptr_testC use size instead of i for indexing. It should be:
sharedptr_testB(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[i]= 'B';
}
(DTTO) for sharedptr_testC)
You start with a vector of size 5, which means it stores five null pointers. Then you append two elements to it (size 7, five nulls + two valid pointers). The you iterate over it, dereferencing each pointer. This of course crashes, since there are nulls at the beginning. Simply initialise the vector as empty.
sharedptr_testA* A = new sharedptr_testA(0);
With these two fixes, the code works.
Side notes 1 (C++):
The code is next to impossible to read. I strongly suggest you use a better naming scheme.
sharedptr_testB and sharedptr_testC leak memory. I understand it's just a learning excercise, I'd just like to point it out. You'd be better off with std::vector<char> in them instead of char*.
Side notes 2 (Stack Overflow):
If you have a crashing program, you should generally try to debug it yourself before asking an SO question. Stepping through the program through a debugger would easily have uncovered both the issues.

How can I do to get correct output in class?

This is the default constructor with no parameters. By default, this allocates space for a
double array of size 10 and assigns a default value of 0 to each of them.
its a ""class"" , I m not sure what i m doing right or wrong..
I fill the public body functions , but my output is nothing suppose to print 0000000000
, I m very new to coding.
class DataVector
{
private:
DataType *m_data;//Pointer to dynamically allocated memory that holds all items
UIntType m_size;//Size of the m_data array
public:
DataVector()
{
double *m_data = new double[m_size];
for (int i = 0; i < m_size; i++)
{
*m_data = 0;
m_data++;
}
}
void PrintItems()
{
for (int i = 0; i < m_size; i++)
{
cout << *m_data << " ";
m_data++;
}
}
};
void TestDataVector()
{
{
DataVector d1;
d1.PrintItems();
}
}
There are a few problems with this implementation of yours:
You are not initializing m_size
You change the value of the pointer m_data which is supposed to hold the address of first member of the array. So, at the end of the initializer, m_data is pointing to a spot one after the block you had allocated by new.
same in the printItems member function, but here the pointer already points to an invalid location.
Also, because you are allocating memory in the constructor, you should also define a destructor to free that memory.

Dynamically allocating array of objects

I need a double pointer of type DizzyCreature (my class) to point to an array of DizzyCreature pointers. When I run it I get "Access violation reading location 0x...". I can make a DizzyCreature* and call its member functions just fine, but when cannot run through the array and do the same thing for each obj.
I am following these instructions:
http://www.cplusplus.com/forum/beginner/10377/
Code
Server.h:
class Server
{
public:
Server(int x, int y, int count);
~Server(void);
void tick();
private:
DizzyCreature** dcArrPtr;
DizzyCreature* dcPtr;
int _count;
};
Server.cpp:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count]; // this works just fine
dcArrPtr = new DizzyCreature*[count]; // this doesn't (but gets past this line)
_count = count;
}
Server::~Server(void)
{
delete[] *dcArrPtr;
delete[] dcPtr;
}
void Server::tick()
{
dcPtr->takeTurn(); // just fine
for (int i = 0; i < _count; i++) {
dcArrPtr[i]->takeTurn(); // crash and burn
}
}
EDIT:
The member function takeTurn() is in a parent class of DizzyCreature. The program makes it into the function, but as soon as it attempts to change a private member variable the exception is thrown. If it matters, DizzyCreature is of type GameCreature and WhirlyB as this is an assignment on MI.
You have allocated space for dcArrPtr, but didn't allocate every object in this array. You must do following:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count];
dcArrPtr = new DizzyCreature*[count];
for ( int i = 0; i < count; i++ ) {
dcArrPtr[ i ] = new DizzyCreature;
}
_count = count;
}
Server::~Server(void)
{
for ( int i = 0; i < count; i++ ) {
delete dcArrPtr[ i ];
}
delete[] *dcArrPtr;
delete[] dcPtr;
}
This:
dcPtr = new DizzyCreature[count];
"creates" an array of DizzyCreatures, whereas:
dcArrPtr = new DizzyCreature*[count];
"creates" an array of pointers to DizzyCreatures, but crucially doesn't create instances for those pointers to point to.
The preferred solution is to use a standard container for tasks like this anyway though. If you really want to do it like this (and are aware that it's not best practice to do this manually) then you'll need a loop to call new for eachelement in the array of pointers.
You allocate an array of count pointers instead of an array of count objects.
Instead of
dcArrPtr = new DizzyCreature*[count];
you might want to
dcArrPtr = new DizzyCreature[count];
You're allocating an array of pointers, but those pointers aren't valid until you set them to something.
double **arr = new double*[10];
for(int i=0;i<10;++i) {
arr[i] = new double[10];
}
That said, when starting out with C++ you should probably avoid raw arrays and instead use std::array and std::vector:
class Server
{
public:
Server(int x, int y, int count);
void tick();
private:
std::vector<std::vector<DizzyCreature>> dcArrPtr;
std::vector<DizzyCreature> dcPtr;
};
Server::Server(int x, int y, int count)
{
dcPtr.resize(count);
dcArrPtr.resize(count);
}
void Server::tick()
{
dcPtr[0].takeTurn();
for (int i = 0; i < dcArrPtr.size(); i++) {
dcArrPtr[i][0].takeTurn();
}
}
Use a
std::vector<std::vector<DizzyCreature>>
Furthermore, if you want to use raw pointers (which I do not recommend), you'll have to allocate memory for each pointer in your array.
class A
{
std::vector<std::vector<int>> v_;
public:
A()
: v_(500, std::vector<int>(500))
{} // 500 x 500
};
class B
{
int** v_;
public:
B()
: v_(new int*[500])
{ // not even exception safe
for (int i = 500; i--; )
v_[i] = new int[500];
}
~B()
{
for (int i = 500; i--; )
delete[] v_[i];
delete[] v_;
}
};
If you would have seen the implementation of dynamic memory allocation of 2-Dimensional array . That would have given you a better insight of how to proceed in such cases . Most of the answers has already answered you what to do . But just go through any link and see how is memory allocated in case of 2-D array . That Will also help you .

Constructor for LinkedList to receive an array C++

Attempting to write a constructor for LinkedList to be initialised with an array of integers.
The program would call linked(array); which will add all the values within the array in to a linkedlist.
LinkedList::LinkedList(int array[])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.length(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
the trouble is the array.length (coming from Java) and I don't think the array length can be obtained this way?
I would suggest you to use iterator idiom, and make the constructor a templated constructor as:
class LinkedList
{
//...
public:
template<typename FwdIterator>
LinkedList(FwdIterator begin, FwdIterator end)
{
for (;begin != end; ++begin)
{
//treat begin as pointer, and *begin as dereferenced object
}
}
//...
};
And then you can use it as:
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr, arr+10);
Not only that. If you've std::vector<int>, then you can also use it to construct the linked list, as:
std::vector<int> v;
//..
LinkedList lnklist(v.begin(), v.end());
So using iterator idiom gives you this much power and flexibility. :-)
As Nawaz explained, going with iterator solution is better. But if you want to go with array ( static one though), then compiler can automatically deduce the size for you.
template<size_t size>
LinkedList::LinkedList(int (&array)[size])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < size++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
Can be called as shown below.
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr);
Like others have said, it is not only important but vital that you get a good introductory C++ book and read it from front to back, simultaneously trying to forget what you know about Java while in C++ mode. They are not remotely similar.
Now to your problem, it can be solved by using std::vector and using its size method:
// put this with the other includes for your file
#include <vector>
LinkedList::LinkedList(const std::vector<int>& array)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.size(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
If you don't want to use vector, you have to pass in the size of the array to the function:
LinkedList::LinkedList(int array[], int arrlen)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < arrlen; ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
But it is recommended to use the vector version.