Why accessing variable declared locally from outside is working? - c++

In tree, while taking input (inside takeInput function), tree node was made using dynamic allocation, but I tried doing it statically, but as tree node were declared inside a function locally it should have not worked because its a local variable (I was expecting a error). But Why am I able print it even after that:
NOTE: this code takes input recursively (and may not be the best way)
#include<bits/stdc++.h>
using namespace std;
template <typename T>
class treeNode{
public:
T data;
vector <treeNode<T>> children;
treeNode(T data){
this->data=data;
}
};
treeNode<int> takeInput(){
int rootdata;
cout<<"Enter Node"<<endl;
cin>>rootdata;
// treeNode<int>* root= new treeNode<int>(rootdata);
treeNode<int> root(rootdata); //Static Allocation
cout<< "Enter Number of children of "<<rootdata<<endl;
int n;
cin>>n;
for(int i=0;i<n;i++){
treeNode<int> child = takeInput();
root.children.push_back(child);
}
return root;
}
void printTree(treeNode<int> root){
cout<<root.data<<": ";
for(int i=0;i<root.children.size();i++){
cout<<root.children[i].data<<",";
}
cout<<endl;
for(int i=0; i<root.children.size();i++){
printTree(root.children[i]);
}
}
int main(){
treeNode<int> root= takeInput();
printTree(root);
return 0;
}
Following code is using dynamic allocation:
#include<bits/stdc++.h>
using namespace std;
template <typename T>
class TreeNode{
public:
T data;
vector <TreeNode<T>*> children;
TreeNode(T data){
this->data=data;
}
};
TreeNode<int>* takeInput(){
int rootdata;
cout<<"Enter node"<<endl;
cin>>rootdata;
TreeNode<int>* root=new TreeNode<int>(rootdata);
cout<<"Enter number of children of "<<rootdata<<endl;
int n;
cin>>n;
for(int i=0;i<n;i++){
TreeNode<int>* child=takeInput();
root->children.push_back(child);
}
return root;
}
void printTree(TreeNode<int>* root){
if (root == NULL){
return;
}
cout<< root->data<<" :";
for(int i=0;i<root->children.size(); i++){
cout<<root->children[i]->data<<",";
}
cout<<endl;
for(int i=0;i<(*root).children.size();i++){
printTree(root->children[i]);
}
}
int main(){
TreeNode<int>* root = takeInput();
printTree(root);
return 0;
}

Your code is equivalent to
A foo() {
A a;
a = bar();
return a;
}
a is just copied into the return value (That copy might be avoided too). Replace A with treeNode<int> and the semantics remain the same.
Why then the dynamic code?
I'm guessing the code version using dynamic allocation was probably coded up thinking that something like
struct A {
std::vector<A> vecA;
};
is a recursive definition for A since when vecA is declared A is an incomplete type. But that's not the case anymore and this is officially into C++17 (though it worked for some compilers in earlier versions too) where some STL containers can do with incomplete type. Hence it used the form
vector <TreeNode<T>*> children;
storing pointers to the children and hence that code, which is similar to the familiar LinkedList Node data structure definition
struct Node {
int data;
Node* next; // The TreeNode stores a vector of pointers instead.
};
Conclusion
Stack allocation is usually preferred when possible since it's faster than the heap route. Also, that code with dynamic allocation brings in the headache of memory management unless smart pointers are being used. It's just not needed for your code. Go with the stack allocation route for your example and let std::vector take care of maintaining the dynamic array.

Related

Using or not using new for creation of a class in another

I have been solving a question, Dijkstra's Algorithm, in C++. I've implemented it using adjacency list.
So I have a class for a node, a class for a minHeap, and a class for the Graph.
class node
{
int vertex,weight;
node *next;
friend class Graph;
friend class minHeap;
public:
node();
node(int,int);
};
node::node(){
vertex=weight=0;
next=0;
}
node::node(int v,int wt){
vertex=v;
weight=wt;
next=0;
}
Do I define the minHeap class this way (without a friend function) and create an object in the getDijkSP() function normally, which allows me to use the object only in that function?
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap];
heapSize=-1;
pos=new int[cap]();
} //eliminating other methods
class Graph
{
node **adjList;
int v;
bool *visited;
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
}
void Graph::getDijkSP(){
minHeap hp(v); //here
hp.addElement(node(0,0));
for(int i=1;i<v;i++)
hp.addElement(node(i,INT_MAX));
while(!hp.isempty()){
node temp=hp.extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp.decreaseKey(current->vertex,current->weight+temp.weight);
}
}
(OR) Do I define the minHeap class with a friend function, so that I can create an object of the minHeap class using the new keyword? (And this helps me define the minHeap object in the scope of the Graph class, so that I can use it in all of its functions for other capabilities as well.)
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
friend class Graph; //say like this
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap]();
heapSize=-1;
pos=new int[cap]();
}
class Graph
{
node **adjList;
int v;
bool *visited;
minHeap *hp; //and do this
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
hp=new minHeap(v); //dynamic allocation
}
void Graph::getDijkSP(){
hp->addElement(node(0,0));
for(int i=1;i<v;i++)
hp->addElement(node(i,INT_MAX));
while(!hp->isempty()){
node temp=hp->extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp->decreaseKey(current->vertex,current->weight+temp.weight);
}
}
I have read this and a few other articles, but specifically want to know the advantages, disadvantages and the appropriateness of both the methods for such similar kinds of questions.
I've provided the constructors for the classes for better clarity.
Short answer would be NO. I would suggest you to read up on smart pointers and rewrite this whole mess. In C++ there is no real reason to use manual allocation in so simple project as this ever.
Also instead of assigning 0 or NULL to a pointer use nullptr, which is C++ symbol only for null pointers unlike the previous mentioned C values that are actually just a int 0 which may cause some unintentional errors.
Edit in response to your comment:
So I've decided to rewrite your code using actual modern C++ instead of this C code with simple classes. In your whole example there are almost no pointers or dynamic allocations needed. I wasn't absolutely sure who exactly should own the actual nodes so from the example I assumed that the MinHeap should. Also I didn't get the point of MinHeap::pos and Graph::visited from what I could see. I can explain any part of that code in more detail, just ask which.
Here is the code:
class Node {
// Only friend class required if you insist on keeping members of Node private.
// If they aren't meant to change, consider declaring them as public and const.
template <unsigned Size> friend class Graph;
public:
Node(int v, int wt) : vertex(v), weight(wt) {}
private:
// Default values written in here right after declarations
// There is no need for a default constructor. You never call it anyway.
int vertex;
int weight;
Node* next = nullptr;
};
// Template parameter because of internal use of std::array.
// If the capacity shouldn't be constant, use std::vector and remove template.
template <unsigned Capacity>
class MinHeap {
public:
// No constructor needed
// ---------------------
// One small tip: write parameter names in function declarations
// even if they aren't needed there for better readability of your code.
void addElement(Node n) { /* impl */ }
Node extractMin() { /* impl */ }
unsigned capacity() { return Capacity; }
bool isEmpty() { return heap.isEmpty(); }
private:
// Default values written in here right after declarations
int heapSize = -1;
std::array<Node, Capacity> heap;
};
// Template parameter because of internal use of std::array.
// If the vertex count shouldn't be constant, use std::vector and remove template.
template <unsigned Vertices>
class Graph {
public:
// No constructor needed
// ---------------------
void getDjikSP() {
hp.addElement({0, 0});
for (unsigned i = 1; i < hp.capacity(); ++i)
hp.addElement({0, INT_MAX});
while (!hp.isEmpty()) {
Node tmp = hp.extractMin();
std::cout << tmp.vertex << " " << tmp.weight << std::endl;
for (Node* current = adjList[tmp.vertex]; current != nullptr; current = current->next)
hp.decreaseKey(current->vertex, current->weight + tmp.weight);
}
}
private:
// Default values written in here right after declarations
std::array<Node*, Vertices> adjList;
MinHeap<Vertices> hp;
};
There is still a lot of space for improvements of this code, for example the MinHeaP::extractMin should maybe return Node&& if it is removed from the heap or const Node& if it should return a reference to the top, etc. To address all the problems and inefficiencies this can still have I would need to see the full code with all functions.

Why is my linked list deleting after a function call?

In the code below I attempt to create a linked list of strings. I then use the linked list to store output generated by a function (named myFunction) which calls itself recursively. When testing/debugging the code, I noticed that if I print the contents of the linked list after executing the function (which should add items to the linked list) nothing prints out. However, if I attempt to print the linked list after adding items from inside the function it works fine.
It appears that the entire linked list is deleted after the call to myFunction. On the other hand, I'm using dynamic memory allocation when I add elements to the linked list so I don't see the issue.
Please help!
#include <cstdlib>
#include <iostream>
template <class T>
class node{
public:
node *next;
T data;
node(){next=0;};
void print();
};
template <class T>
void node<T>::print(){
std::cout << data;
}
template <class T>
class List{
public:
node<T> *head;
List(){head=0;};
void add(T data);
void print();
int len();
};
template <class T>
int List<T>::len(){
int i=0;
node<T> *current=head;
while(current!= 0){
i++;
current=current->next;
}
return i;
};
template <class T>
void List<T>::add(T myData){
node<T> *current=head;
if(head==0){
head= new node<T>;
head->data=myData;
}
else{
while(current->next!=0){
current=current->next;
}
current->next = new node<T>;
current->next->data=myData;
}
}
template <class T>
void List<T>::print(void){
node<T> *current=head;
if(head==0){
return;
}
else{
do{
std::cout << current->data << " ";
current=current->next;
}while(current!=0);
}
}
void myFunction(List<std::string> myList, int n, std::string starter, int leftParens, int rightParens){
int remainingLength = leftParens+rightParens;
if(remainingLength==0){
myList.add(starter);
std::cout <<myList.len() << std::endl;
}
if(leftParens >0){
myFunction(myList, n, starter+"(", leftParens-1, rightParens);
}
if(leftParens==0 and rightParens >0){
myFunction(myList, n, starter+")", leftParens, rightParens-1);
}
}
int main(int argc, char** argv) {
List<std::string> myList;
myFunction(myList, 5, "", 5, 5);
std::cout <<myList.len();
}
You are passing myList to myFunction by value. Any changes made to myList in the function are changes to the copy, not the original myList in main.
Change myFunction so that it accepts its argument by reference. Then, any changes made to it in myFunction will also be visible in main.
void myFunction(List<std::string>& myList, int n,
// ^^
std::string starter, int leftParens, int rightParens){
You need to use reference if you want to update the variable in the caller context (in other words, if you want to change the variable in main).
Whenever a class allocates memory, you probably need to follow the "rule of three" (constructor, copy-constructor, copy-assignment operator). If you don't, you'll get into trouble if you ever make a copy of the original class [like your call to myFunction as it currently stands]

C++ How may I return an array class member of a nested class?

This is not a real question, since I've already solved the problem myself, but I still need some clarifications about the mechanism behind assigning an array's address to a pointer of the same type when the array is a class member of a nested class.
The following code is fully functioning, although it may lack some error_check. It is only meant to show how I made my (real) program work.
HEADER (linkedList)
class linkedList
{
public:
linkedList();
~linkedList();
int* getArray();
void forward();
private:
class listNode
{
public:
listNode();
~listNode();
friend class linkedList;
private:
int array[3];
listNode* next;
};
listNode *first;
listNode *current;
};
CPP (linkedList)
linkedList::linkedList()
{
first = new listNode;
current = first;
}
//~~~~~~~~~~~~
linkedList::~linkedList()
{
delete first;
first = 0;
current = 0;
}
//~~~~~~~~~~~~
int* linkedList::getArray()
{
if (current)
{
return &(current->array[0]);
}
}
//~~~~~~~~~~~~
void linkedList::forward()
{
if (current->next)
{
current = current->next;
}
}
//-------------------------
//-------------------------
//-------------------------
linkedList::listNode::listNode()
{
next = 0;
for (int i = 0; i < 3; i++){array[i]=((i+1)*3);}
}
//~~~~~~~~~~~~
linkedList::listNode::~listNode()
{
}
CPP (main)
#include <iostream>
#include "linked_list.h"
using namespace std;
int main()
{
linkedList list;
int *myArray;
myArray = list.getArray();
for (int i = 0; i < 3; i++){cout << myArray[i] << " ";}/**/cout << "\n\n";
return 0;
}
The real program is meant to move through a linked list made of nodes which contain 3 integer values in an array of int type, retrieve the three values and use them as parameters for some other functions.
Now, to do so I have to return the address to the first element of the array contained in the node through an accessor.
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
Why?
I've got to this solution through trial and error with very little knowlegde of the reasons that brought me to build this expression as it is.
Usually, when you want to assign the address of an array to a pointer, you just do so:
int main()
{
int array[3];
int* pArray;
pArray = array;
}
And that's it, because the name of the array itself is enough to retrieve the address of its first element.
The exact same result can be achieved by doing this (tested):
int main()
{
int array[3];
int* pArray;
pArray = &(array[0]);
}
Both methods are also valid when the accessor returns the address from a member variable of its own class.
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
What are the logic stages that make it the only viable method?
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
You aren't:
return current->array;
and
return &(current->array[0]);
Both do the same thing when the return type is int*. You aren't forced to use the second way.
Also, there's a bug in getArray. You don't return anything if current is null.
To be pedantic...
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
You're returning the address i.e. a pointer. Reference means something else.

Nothing to build: Eclipse Issues for C++

I have some experience with Java and Eclipse, but I'm new to C++, and trying to teach myself. I apologize if this is a simple question, or one that has already been asked (though I looked around for a while.) I'm on a Windows 8.
I'm trying to make a sorted linked list (which is relatively unimportant.) I get:
Info: Nothing to build for Working.
Here's my code:
/*
* SortedList class
*/
#include <string>
#include <fstream>
#include<iostream>
#include "SortedList.h"
using namespace std;
//the ListNode Structure
struct ListNode {
string data;
ListNode *next;
};
//the head of the linked list and the pointer nodes
ListNode head;
ListNode *prev, *current;
// insert a string into the list in alphabetical order
//now adds a string to the list and counts the size of the list
int Insert(string s){
//make the new node
ListNode temp;
temp.data = s;
//the node to traverse the list
prev = &head;
current = head.next;
int c = 0;
//traverse the list, then insert the string
while(current != NULL){
prev = current;
current = current->next;
c++;
}
//insert temp into the list
temp.next = prev->next;
prev->next = &temp;
return c;
}
//Return the number of times a given string occurs in the list.
int Lookup(string s){
return 0;
}
//prints the elements of the list to ostream
void Print(ostream &output){
}
int main( int argc, char ** argv ) {
cout << Insert("a") << endl;
cout << Insert("b") << endl;
cout << Insert("d") << endl;
}
And here's my header:
using namespace std;
#ifndef SORTEDLIST_H_
#define SORTEDLIST_H_
class SortedList {
public:
// constructor
SortedList();
// modifiers
int Insert(string s);
// other operations
int Lookup(string s) const;
void Print(ostream &output) const;
private:
struct ListNode {
string data;
ListNode *next;
};
// pointer to the first node of the list
ListNode head;
ListNode *prev, *current;
};
#endif /* SORTEDLIST_H_ */
Any help would be greatly appreciated.
Why don't you use std::deque (in header deque)? It probably has all the functionality you are seeking, it is fully tested and optimised. If you need a deque with a bit more of functionality, create a class that inherit from it and add the functions you need. Have a look to http://en.cppreference.com/w/cpp/containe and pick up the container that best suits your needs.
As a general advise, if something you need is already available in some good and stable library (STL, boost, GSL, Armadillo or similar), much better use it rather than to write+debug+optimise it yourself from scratch. As a general advise, focus your efforts on the code that is unique to your application, and reuse what has already be done (BUT only if it has been well tested, do not use crappy half cooked libraries).

Binary tree (reading from file)

#include <iostream>
#include <string>
#include <fstream>
using namespace std;
template <class T>
struct TreeNode{
string value;
T key;
TreeNode<T> *LeftChild;
TreeNode<T> *RightChild;
TreeNode (T k,string Val)
{
this->value=Val;
this->key=k;
this->LeftChild=NULL;
this->RightChild=NULL;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T> *Root;
public:
BinaryTree();
void insertNode();
};
template <class T>
BinaryTree<T>::BinaryTree()
{
Root=NULL;
ifstream fin;
fin.open("names.txt");
string buffer;
T buff;
while (!fin.eof())
{
getline(fin,buffer,'~');
fin>>buff;
cout<<buff<<buffer<<endl;
cout<<"down the tree"<<endl;
TreeNode<T> *temp=Root;
while (temp!=NULL)
{
TreeNode<T> *Right=temp->RightChild;
TreeNode<T> *Left=temp->LeftChild;
if (temp->key>buff)
{
temp=temp->LeftChild;
}
else if (temp->key<buff)
temp=temp->RightChild;
}
cout<<"further down"<<endl;
}
temp->value=buffer;
temp->key=buff;
cout<<"and done!"<<endl;
cout<<"hey"<<endl;
}
fin.close();
}
I am making a binary tree. There are pointers to left and right child in my tree and a key and a string value for each node. In my destructor I am reading from a file and storing the key and value in a node. Every line of the file has the following format:
"M. Ubiquity~ 14100148"
- the Value is the name followed by the key.
Whenever I run this code, I get segmentation fault error but I can't seem to find the fault.
Any hint/help will be appreciated.
You have Root=NULL; and then few lines later TreeNode<T> *temp = Root; so you have temp=NULL.
Obviously the while (temp!=NULL) never executes and after while loop you have temp->value=buffer; which cause segementation fault!
Pointers can only associated with memory addresses, not values. Mainly there are two ways: If you have an automatic variable, you can assign its address to a pointer like this:
int i = 6; //automatic variable
int *pi = &i;
std::cout << pi; // you get the address of pi (hexadecimal number)
std::cout << *pi; // 6
Or you can allocate memory manually. The main thing is if you allocated memory to a variable, you also have to deallocate it or your program will have "memory leak".
int *pi = new int(6);
delete pi;
So if you place new elements in the tree, you have to allocate memory for them, and if you delete an element, you have to destruct with delete. You have to care about not to broke the list.