C++ Template Class - c++

Hey..
I'm having trouble with some homework.
We are working on VectorList ( kinda like linked list but with vectors - don't ask why.. )
Anyway I have something like this:
#ifndef VECTORLIST_H
#define VECTORLIST_H
#include <iostream>
#include <vector>
using namespace std;
template< typename NODETYPE >
class VectorList
{
public:
VectorList(); // constructor
~VectorList(); // destructor
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
vector< NODETYPE > *vList; // list data as a vector
};
I need to fill in the functions.. my problem is that I do not understand how
to use STIL when I have *vList.. its a pointer to the first vector element?
// display contents of VectorList
template< typename NODETYPE >
void VectorList< NODETYPE >::print() const
{
// Fill in the missing code
}
My Idea was to use a for loop on the vector and use cout<< vector[i]<< endl;
to print the vector out..
Problem is that I get all sorts of errors and seg faults.
I do not understand how to access the vector in the function,
and how to access its elements.
This is a header file, and in the main we declare an object of VectorList<NODETYPE> IntVector...
So how can I do this?
Any help with understanding of how this *vList plays a role here would help a lot and
I'd probably be able to finish the rest..
Also, for isEmpty(), I assume I can use vList.empty().. but since vList is a pointer..
it doesn't work quite well.
== For the constructor/destructor what can I do?
I know for destructor I should iterate through the vector and use delete on each element.
But shoul
Please explain this to me, I am frustrated =[

my problem is that I do not understand how to use STL when I
have *vList.. its a pointer to the first vector element?
I assume that you are required as part of your homework to use pointer-to-vector instead of a vector itself. As a rule, I never use pointers-to-containers. In fact, the best thing that I discovered in switching from C to C++ was that I could write entire programs with no pointers at all, thanks to STL programming. Unless you are required to use pointer-to-vector, I recommend that you use the vector directly.
Certainly it is easier to use the vector proper than a pointer, but don't worry. Using the pointer isn't too bad.
First, in order to use a pointer-to-something, one must allocate the something. So, in your constructor, invoke new.
vList = new std::vector<NODETYPE>;
Anytime we invoke new, we must have a matching delete somewhere. Since our new is in our constructor, we need to invoke delete in the destructor:
delete vList;
You said:
but since vList is a pointer.. it doesn't work quite well.
Here is where life gets easy. Generally, if p is a pointer to some type, then (*p) is the object to which p points. Here are some examples:
int i = 1;
int *pInt = &i;
i = 4;
(*pInt) = 4;
std::cout << i << " " << (*pInt) << "\n";
std::vector<NODETYPE> v;
std::vector<NODETYPE> *pVector;
v.push_back();
(*pVector).push_back();
it = v.begin();
it = (*pVector).end();
So, invoking members of vList is easy : (*vList).empty().
So, your code might be :
void insertAtFront(const NODETYPE& node) { (*vList).push_front(node); }
There is a short-cut operator -> that makes the above somewhat easier to read:
void insertAtFront(const NODETYPE& node) { vList->push_front(node); }
The expression x->y is more-or-less equivalent (*x).y.
To sum up:
Allocate your vList in your constructor with new. Destroy your vList in your destructor with delete. Invoke members of vList using either (*vList).function() or vList->function().
Good luck, and come back if you have other questions!
P.s. Since you have a non-trivial destructor, you'll need to consider the rule of three.
P.P.s. You said something about iterating the vector in your destructor and deleting each of the objetcs you find there. You would only need to do that if your data type were vector-of-pointers-to-NODETYPE (contrast to what you declared: pointer-to-vector-of-NODETYPE). Until and unless you become completely comfortable with pointers, I recommend that you never store pointers in STL containers.

You should construct your object in the constructor (if you really need using bare pointers): vList = new vector< NODETYPE >();, free memory in the destructor: delete vList;, translate your methods to corresponding methods of the container class. For example, insertAtBack would be implemented as vList->push_back(elem);

Related

C++ Tree Data Structure

Background:
So I've been porting some of my older Java code to C++, and I've come across an issue that's making proceeding quite difficult. My project uses a tree data-structure to represent the node hierarchy for 3D animation.
Java:
public final class Node {
private final Node mParent;
private final ArrayList<Node> mChildren;
//private other data, add/remove children / parents, etc ...
}
In Java, its quite simple to create a tree that allows for modification etc.
Problem:
I'm running into issues is with C++, arrays cannot easily be added to without manually allocating a new chunk of memory and having the existing ones moved over so I switched to std::vector. Vectors have the issue of doing what I just described internally making any pointers to there elements invalid. So basically if you wan't to use pointers you need a way to back them so memory holding the actual nodes doesn't move. I herd you can use std::shared_ptr/std::unique_ptr to wrap the nodes in the std::vector, and I tried to play around with that approach but it becomes quite unwieldy. Another option would be to have a "tree" class that wraps the node class and is the interface to manipulate it, but than (for my use case) it would be quite annoying to deal with cutting branches off and making them into there own trees and possibly attaching different branches.
Most examples I see online are Binary trees that have 2 nodes rather than being dynamic, or they have many comments about memory leaks / etc. I'm hoping there's a good C++ alternative to the java code shown above (without memory leak issues etc). Also I won't be doing ANY sorting, the purpose of the tree is to maintain the hierarchy not to sort it.
Honestly I'm really unsure of what direction to go, I've spent the last 2 days trying different approaches but none of them "feel" right, and are usually really awkward to manage, any help would be appreciated!
Edit:
An edit as to why shared_ptrs are unwieldy:
class tree : std::enable_shared_from_this<tree> {
std::shared_ptr<tree> parent;
std::vector<std::shared_ptr<tree>> children;
public:
void set_parent(tree& _tree) {
auto this_shared_ptr = shared_from_this();
if (parent != nullptr) {
auto vec = parent->children;
auto begin = vec.begin();
auto end = vec.end();
auto index = std::distance(begin, std::find_if(begin, end, [&](std::shared_ptr<tree> const& current) -> bool {
return *current == this_shared_ptr;
}));
vec.erase(std::remove(begin, end, index), end);
}
parent = std::shared_ptr<tree>(&_tree);
if (parent != nullptr) {
parent->children.push_back(this_shared_ptr);
}
}
};
working with pointers like above becomes really quite verbose, and I was hoping for a more simple solution.
You could store your nodes in a single vector and use relative pointers that are not changed when the vectors are resized:
typedef int32_t Offset;
struct Node {
Node(Offset p) : parent(p) {}
Offset parent = 0; // 0 means no parent, so root node
std::vector<Offset> children;
};
std::vector<Node> tree;
std::vector<uint32_t> free_list;
To add a node:
uint32_t index;
if (free_list.empty()) {
index = tree.size();
tree.emplace_back(parent_index - tree.size());
} else {
index = free_list.back();
free_list.pop_back();
tree[index].parent = parent_index - index;
}
tree[parent_index].children.push_back(index - parent_index);
To remove a node:
assert(node.children.empty());
if (node.parent) {
Node* parent = &node + node.parent;
auto victim = find(parent->children.begin(), parent->children.end(), -node.parent);
swap(*victim, parent->children.back()); // more efficient than erase from middle
parent->children.pop_back();
}
free_list.push_back(&node - tree.data());
The only reason for the difference you're seeing is if you put the objects directly in the vector itself in c++ (which you cannot do in Java.) Then their addresses are bound to the current allocated buffer in the vector. The difference is in Java, all the objects themselves are allocated, so only an "object reference" is actually in the array. The equivalent in c++ would be to make a vector of pointers (hopefully wrapped in smart pointer objects) so the vector elements only are an address, but the objects live in fixed memory. It adds an extra pointer hop, but then would behave more like what you expect in java.
struct X {
char buf[30];
};
std::vector<X> myVec{ X() };
Given the above, the X elements in myVec are contiguous, in the allocation. sizeof(myVec[0]) == sizeof(X). But if you put pointers in the vector:
std::vector<unique_ptr<X>> myVec2{ make_unique<X>() };
This should behave more like what you want, and the pointers will not become invalid when the vector resizes. The pointers will merely be copied.
Another way you could do this would be to change things a little in your design. Consider an alternate to pointers entirely, where your tree contains a vector of elements, and your nodes contain vectors of integers, which are the index into that vector.
vector, forward_list, ..., any std container class (other than built-in array or std::array) may be used.
Your trouble seems to be that java classes are refrence types, while C++ classes are value types. The snippet below triggers "infinite recursion" or "use of incomplete type" error at compiletime:
class node{
node mParent;//trouble
std::vector<node> children;
//...
};
the mParent member must be a reference type. In order to impose reference semantics you can make it a raw pointer:
node* mParent;
you may also use pointer as the argument type to the container, but as a C++ beginer that would most probably lead to memory leaks and wierd runtime errors. we should try to stay away from manual memory management for now. So the I modify your snippet to:
class node{
private:
node* const mParent;
std::vector<node> children;
public:
//node(node const&)=delete;//do you need copies of nodes? you have to properly define this if yes.
node(node *parent):
mParent{parent}{};
void addChild(/*???*/){
children.emplace_back(this);
//...
};
//...
};

Copy constructor for a vector of pointers

I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};

Unable to populate vector inside struct

I'm new to C++ so bear with me.
I made a struct that looks like this:
struct node{
double startPoint;
double endPoint;
vector<node*> children;
void addChild(node *aNode){
children.push_back(aNode);
}
void addPoints(double start, double end){
startPoint = start;
endPoint = end;
}
};
Down the line in my program, I have the following:
vector<node*> data;
....
node *temp = (node*)malloc(sizeof(node));
temp->addPoints(lexical_cast<double>(numbers[0]), lexical_cast<double>(numbers[1]));
data[index]->addChild(temp);
where "Index" is a index of the vector data. the lexical_cast stuff is taking those numbers from string to doubles.
Everything works until the addChild(temp) line.
The terminal spit this out:
First-chance exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
Unhandled exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
But I have no idea how to deal with that.
malloc allocates some space, but doesn't put anything in it. It works fine for plain-old-data structures (or trivially initializable classes), and in C that's all you have.
In C++ you have classes, like std::vector amongst others, which need to be properly constructed in order to establish some invariants. This is done with a straight declaration for objects with automatic storage duration, but for dynamically-allocated objects you need to use new instead of malloc.
For example,
std::vector<int> global; // (1)
void foo() {
std::vector<int> local; // (2)
std::vector<int> *bad = malloc(sizeof(*bad)); // (3)
std::vector<int> *good = new std::vector<int>; // (4)
std::unique_ptr<std::vector<int>> better(new std::vector<int>); (5)
}
is fine - this global is initialized (by which I mean the constructor is called) automatically
is fine - this local variable is also constructed automatically, and destroyed properly as soon as foo exits
you can't use bad for anything, because any method you call will assume the constructor ran already, and it didn't
ok, you can't use bad for anything without explicitly constructing it using placement new. You shouldn't do this though, it's only appropriate where you're doing clever or tricky stuff with custom allocation.
this is ok (but note you have to delete it manually - foo has a memory leak)
this is better - you don't need to clean up manually
Now, note that your node class also has a constructor. In this case, it's automatically-generated, and does nothing but call the vector constructor. Still, you need it to be called, which means using new for dynamically allocating a node.
So, your program should probably look more like:
std::vector<std::unique_ptr<node>> data;
...
std::unique_pre<node> temp(new node);
temp->addPoints(...);
data[index]->addChild(temp);
Note I'm assuming data[index] is valid (I see from addChild you know how to populate a vector already), and that the single-owner model implemented by unique_ptr is appropriate.
As far as the code I see, you never add any nodes into the data array
data.push_back(something);
So accessing data[index] would be out of the allocated memory of the array. It won't complain until you try to set memory in that block (via addChild trying to push an element into the children array).
I would recommend that you store a node instead of a node* in your vector so you don't have to manage the memory on your own.
this is C++ so you don't have to malloc the space for a node you can use new like so:
Node * n = new Node();
New is much better because it calls the constructor and allocates space, whereas malloc just does the latter.
You haven't shown much of your code, but I would restructure the node class like this.
struct node{
double startPoint;
double endPoint;
vector<node> children;
node(){} //add default constrcutor
void addChild(node aNode){
children.push_back(aNode);
}
node & operator=(const node & n) {
startPoint = n.startPoint;
endPoint = n.endPoint;
return *this;
}
node(double start, double end): startPoint(start),endPoint(end){
} //in c++ you have constructors which this should have been in the first place
//constructors are used for initializing objects
};
this is better is that now you can't pass add child nullptr avoiding a lot of problems in your code. You also have a constructor now. Now you can add a node like this.
node temp(start,end); data[index]=temp;
You have a constructor now which addPoints should have been in the first place
I also made an assignment operator
Using the style of coding where you allocate memory on the stack and don't use new is called RAII and is a vital technique for learning c++ and producing exception safe code, this is the main reason I advocate not storing node*'s

C++ adjacency list of pointers and structs

Working on adjacency list --> directed weighted graph
One class looks like this, i.e. header:
class CGraph;
class CMap {
public:
//voided constructors and destructors
//functions one is:
void SetDirGraph(string commands);
private:
CGraph* m_myMap;
};
Second class:
class CNode {
public:
//voided constructor and desctructor
int m_distance, m_vert;
bool m_isKnown;
};
typedef struct edges {
int v2, weight;
} edge;
class CGraph {
public:
CGraph(int map_size);
~CGraph(void);
void AddMap(int v1, int v2, int weight);
void AddEndVert(int v2, int weight);
private:
list<edge> List;
int size;
public:
CNode* verts;
};
I'm reading vertices from a file, and that works. My problem is I am having trouble creating an adjacency list based on the code given. I'm trying to use pointers first that points to a list and it is not working correctly. I don't know how to create my pointers to the list without writing over them.
void CMap::SetDirGraph(string command) {
istringstream buffer(command)
char ch;
int num, vert1, vert2, weight; //specify vertices and weight and number of vertices
buffer>>ch; //throw away first character (not needed)
buffer>>num // size of vertices
while(!buffer.eof()) { // keep reading until end of line
buffer>>v1; // vertex start
buffer>>v2; // vertex end
buffer>>weight;
m_myMap = new CGraph(map_size); //initialize m_myMap.
m_myMap->verts->m_vert = v1; // mymap->verts->vert points to first edge
m_myMap->AddMap(v1, v2, weight); // create list?
m_myMap->AddEndVert(v2, weight); //create list? push v2 and weight on my list using my list.
}
}
I've tried several different ways and I keep confusing myself, any point in the right direction would be awesome.
EDIT:
I have more code too if needed to be produced, just publishing the main stuff.
What I mean by "not working" is that I am just writing over the previous vertex. I don't know if I should create an array using m_myMap (tried and still writes over and get a memory error as well). No compiler errors.
I don't know how to create my pointers to the list without writing over them.
Apart from your application, the answer to this question is the new operator, which I assume you are aware of, since you used it within your example code. Code like int * a = new int(42); allocates memory for an int on the heap and you are responsible for cleaning it up when it is not needed anymore. You thereby have full control over how long a variable will be available. In int x = 42; int * a = &x; on the other hand, x will automatically be cleaned up when it runs out of scope, and a will be a pointer to a memory block that has no meaningful data in it anymore. If you try to dereference it, you will encounter undefined behavior, and, if you are lucky, your program will blow up.
If you can use the C++11 standard, or a library that offers smart pointers, you should prefer those over managing the pointer yourself whenever possible. A smart pointer is an object that holds the allocated memory and frees it automatically when it is destructed. More specific information depends heavily on which sort of smart pointer you are using. The reason for using smart pointers is that doing the management yourself is tedious and error prone. If you do not delete your pointers you had allocated, your application will keep on allocating more memory until it blows up some day (depending on how often and how much memory you allocate); this is called leaking. If you call delete more than once, your program will bail out as well. Here is an example of C++11 shared_ptr in your application:
class CMap
{
private:
std::shared_ptr<CGraph> m_myMap;
// etc.
};
// in SetDirGraph
m_myMap.reset( // if the smart pointer has previously been managing
// memory, it will free it before allocating new
new CGraph(map_size) // allocate CGraph as before
);
Besides that, what hopefully answers your question, I have run into several potential problems concerning your code:
Definitely wrong:
In SetDirGraph you set m_myMap->verts->m_vert = v1. m_myMap->verts is a pointer. You have freshly created m_myMap and thus verts is not initialized, hence pointing at a random block of memory. You then try to dereference it by m_myMap->verts->m_vert = v1. This cannot work. You need to create verts first, i.e. verts = new CNode;.
typedef struct edges { /* etc */ } edge; is a C construct and there is no need for the typedef wrapper in C++. It does work and all, but it is really redundant and lots of those constructs just pollute the namespace you are working in.
Do you really need pointers in the first place? Your provided snippets do not hint at why you would need to use them. You will want to reduce usage of pointers to a minimum (or at least use smart pointers, see above)

What is the problem with this piece of C++ queue implementation?

I'm trying to write a linked queue in C++, but I'm failing so far. I've created 2 files by now: my main.cpp and box.h. When trying to use my box, I receive the following message:
Description Resource Path Location Type
conversion from ‘Box*’ to
non-scalar type ‘Box’
requested main.cpp /QueueApplication line
14 C/C++ Problem
My code is as follows:
box.h
#ifndef BOX_H_
#define BOX_H_
template<class T>
class Box
{
public:
Box(T value)
{
this->value = value;
this->nextBox = NULL;
}
T getValue()
{
return this->value;
}
void setNext(Box<T> next)
{
this->nextBox = next;
}
private:
T value;
Box<T> nextBox;
};
#endif /* BOX_H_ */
main.cpp
#include<iostream>
#include "box.h"
using namespace std;
int main(int argc, char** argv)
{
Box<int> newBox = new Box<int>();
cout << "lol";
cin.get();
cin.ignore();
return 0;
}
Could you guys help me?
PS: before someone ask me why not to use stl ... I'm in a data structures class.
Removing unimportant stuff, we see you've declared a new class like this:
template<class T>
class Box
{
T value;
Box<T> nextBox;
};
How big is Box<T>?
Clearly
sizeof Box<T> >= sizeof(Box<T>::value) + sizeof(Box<T>::nextBox)
sizeof Box<T> >= sizeof(T) + sizeof(Box<T>)
0 >= sizeof (T)
uh-oh
The problem is with this line
Box<int> newBox = new Box<int>();
The new operator returns a pointer to a Box object created on the heap. The pointer will be of type Box<int>*. The left side of that expression declares a Box object. You can't directly assign a pointer-to-X to an X. You should probably just omit the new keyword unless you have a reason to want to manage the storage lifetime of the object manually. Incidentally, I'm betting you come from Java, where new is always required to create objects. Not so in C++.
Also I think it's awesome that your data structures class is introducing you to templates right off the bat.
I believe your nextBox should be a pointer.
Box<T> * nextBox;
Method setNext should deal with pointers too.
void setNext(Box<T> * next)
And newBox should be a pointer.
Box<int> * newBox = new Box<int>();
Since you come from a Java background, you are assuming that all of your objects are references. Syntax is a little different in C++.
There are multiple problems here.
First of all, in order to implement a linked list (or a queue that uses a linked list) in C++ you need to use pointers. In Java everything is a reference. C++, on the other hand, makes a clear distinction between objects and pointers to objects. (There are also references to objects, but they are irrelevant here).
Let's also forget the templates for a moment, because they are not part of the problem here.
class Box
{
int value;
Box nextBox; // wrong! should be a pointer
};
is wrong, because nextBox must be a pointer to the next element of the list/queue. The correct
way would be Box *nextBox;
By the same token setNext() should also take a pointer to Box as its argument. setNext(Box b) is an example of pass-by-value, i. e. this member function (method in Java lingo) gets its own copy of the entire Box object. This could lead to performance issues if the object is large, not to mention that any changes done to it by the function will be invisible to the caller. What you want instead here is pass-by-reference, which is accomplished by using a pointer.
The final point is that new in C++ always returns a pointer. You should have Box<int> *newBox = new Box<int>;
When you use new, you get a pointer to an object, not a plain object. Declare your variable as a pointer or just allocate your object on the stack instead.
I hope this makes sense to you, since if it doesn't, you should probably go back and read more about the basics of OOP in C++.
Guys. No raw pointers in C++ unless you really need them. Please. Especially for some poor soul who doesn't even know that operator new returns a pointer. Get a std::auto_ptr or a std::shared_ptr.