Copy constructor for a vector of pointers - c++

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);
...
};

Related

How to avoid using new operator in C++?

I have a C++ program that creates Huffman codes for all characters in file. It works good, but I want to create nodes without using new operator because I know that you shouldn't use it. I tried using a vector global variable for saving nodes but that doesn't work.
std::vector<Node> nodes;
Node* create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
Node temp;
temp.m_value = value;
temp.m_counter = counter;
temp.m_left = left;
temp.m_right = right;
nodes.push_back(temp);
return &nodes[nodes.size() - 1];
}
Edit: I added more code, I did't really explained what doesn't work. Problem is in generate_code(), it never reaches nullptr. I also tried using Node and not Node* but the same thing happened.
void generate_code(Node* current, std::string code, std::map<unsigned char, std::string>& char_codes) {
if (current == nullptr) {
return;
}
if (!current->m_left && !current->m_right) {
char_codes[current->m_value] = code;
}
generate_code(current->m_left, code + "0", char_codes);
generate_code(current->m_right, code + "1", char_codes);
}
void huffman(std::ifstream& file) {
std::unordered_map<unsigned char, ull> char_frequency;
load_data(file, char_frequency);
std::priority_queue<Node*, std::vector<Node*>, Comparator> queue;
for (auto& node : char_frequency) {
queue.push(create_node(node.first, node.second, nullptr, nullptr));
}
while (queue.size() != 1) {
Node* left = queue.top();
queue.pop();
Node* right = queue.top();
queue.pop();
auto counter = left->m_counter + right->m_counter;
queue.push(create_node('\0', counter, left, right));
}
std::map<unsigned char, std::string> char_codes;
Node* root = queue.top();
generate_code(root, "", char_codes);
for (auto& i : char_codes) {
std::cout << +i.first << ": " << i.second << "\n";
}
}
The general answer is of course to use smart pointers, like std::shared_ptr<Node>.
That said, using regular pointers is not that bad, especially if you hide all pointers from the outside. I wouldn't agree with "you shouldn't use new", more like "you should realize that you have to make sure not to create a memory leak if you do".
In any case, for something like you do, especially with your vector, you don't need actual pointers at all. Simply store an index for your vector and replace every occurence of Node* by int, somewhat like:
class Node
{
public:
// constructors and accessors
private:
ValueType value;
int index_left;
int index_right;
}
I used a signed integer as index here in order to allow storing -1 for a non-existent reference, similar to a null pointer.
Note that this only works if nothing gets erased from the vector, at least not before everything is destroyed. If flexibility is the key, you need pointers of some sort.
Also note that you should not have a vector as a global variable. Instead, have a wrapping class, of which Node is an inner class, somewhat like this:
class Tree
{
public:
class Node
{
...
};
// some methods here
private:
vector<Node> nodes;
}
With such an approach, you can encapsulate your Node class better. Tree should most likely be a friend. Each Node would store a reference to the Tree it belongs to.
Another possibility would be to make the vector a static member for Node, but I would advise against that. If the vector is a static member of Node or a global object, in both cases, you have all trees you create being in one big container, which means you can't free your memory from one of them when you don't need it anymore.
While this would technically not be a memory leak, in practice, it could easily work as one.
On the other hand, if it is stored as a member of a Tree object, the memory is automatically freed as soon as that object is removed.
but I want to create nodes without using new operator because I know that you shouldn't use it.
The reason it is discouraged to use new directly is that the semantics of ownership (i.e. who is responsible for the corresponding delete) isn't clear.
The c++ standard library provides the Dynamic memory management utilities for this, the smart pointers in particular.
So I think your create function should look like follows:
std::unique_ptr<Node> create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
std::unique_ptr<Node> temp = std::make_unique<Node>();
temp->m_value = value;
temp->m_counter = counter;
temp->m_left = left;
temp->m_right = right;
return temp;
}
This way it's clear that the caller takes ownership of the newly created Node instance.

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);
//...
};
//...
};

c++ store items into an array

I have this code that in my mind, it recieved an item called Vehicle and it has to store it in an array called Node. This is the code related to this part of the program:
void Table::process(Vehicle v, int cont) {
char a='A'+cont;
putVehicle(a,v);
Node.a_v[cont]=v;
if(cont==0) a_surt=v.rowVehicle();
}
This is how I have the array on the private part of Table.h:
struct Node{
Vehicle a_v;
};
The error I get is:
error: expected primary-expression before '.' token
I have the includes I need, but everytime I type this: Node.a_v It gives me that error.
Any advice?
If you want to use a struct, you need to declare a Node before using it. Also, the struct needs to contain an array (or better, look into vectors for more flexibility).
struct Node {
Vehicle[10] a_v; // 10 is max number of Vehicles in array
};
Node myNode;
myNode.a_v[cont] = v;
Remember that if you want to keep this Node around and put more things in it, it needs to be declared in the right scope. For example, to have your process function add a Vehicle to a Node that exists outside of the function process, you could something like this:
void Table::process(Node n, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) {
n.a_v[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
It kind of looks like you're just trying to use an array. In that case you're looking for something like this:
// This would go somewhere in your program. Again, 10 is just an example.
Vehicle vehicleArray[10];
// Send this array to this function
void Table::process(Vehicle[] vArray, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) { // In a real program, don't hard-code array limits.
vArray[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
You should use Node object to get access to the a_v variable. This line
Node.a_v[cont]=v;
Is incorrect. You should do something like that:
Node n;
n.a_v[cont]=v;
everytime I type this: Node.a_v It gives me that error.
Node is a type; types define the structure of a objects, but they do not have fields of their own (except the static fields, which belong to all instances at once; they are accessed differently anyway).
In order to use a . or -> operator, you need an instance of a Node, like this:
Node x;
x.a_v = ...
It is not clear in your case from where the Node instances should be coming, though. In order to access them, you would need to either pass them in as parameters, or make them available statically/globally (not recommended).
Okay, so Node is NOT the name of your array. It's the name of a user-defined type that is supposed to contain an array. Your Node, however, does not contain an array. It contains one Vehicle, named a_v. I assume a_v is supposed to represent an Array of Vehicles. Therefore, you need to allocate the array. Something like this:
struct Node {
Vehicle a_v[AMOUNT];
};
If you don't know at compile-time how large you want your arrays to be, then they must be dynamically allocated, like this:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
};
If it's dynamically allocated, then it must also be deallocated:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
};
AND if it's dynamically allocated, you need to add provisions for copying or disable copying:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
// Disable copies (with C++11 support):
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// Disable copies (without C++11 support) by making them private and not defining them.
private:
Node(const Node&);
Node& operator=(const Node&);
};
Then to access one of the Vehicles, you'd need to do so like this:
Node n; // Declare a node, which contains an array of Vehicles
n.a_v[cont] = v; // Copy a Vehicle into the array of Vehicles
Note, however, that if you declare the Node instance in this function, then it is local and it will go out of scope as soon as your function ends. You need to declare the Node instance as a member of your Table if you want it to persist past the function call.
class Table
{
private:
Node n;
};
Lastly, as others have suggested, I'd highly recommend that you read a C++ book to learn C++. My personal recommendation is this book (5th edition, don't buy 6th or 7th - the author of those editions is terrible).

Find an edge using the Ford Fulkerson algorithm?

I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.

C++ Template Class

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);