Issue when implementing a Node class - c++

Can someone please tell me what is wrong with the following code ? I am trying to implement
a graph with a class Node which contains the node id and a vector of pointer to its neighbors. Here is a short version of my code :
#include<vector>
#include<iostream>
using namespace std;
class N {
public:
int i;
vector<N*> v;
N(int i) {
this->i = i;
};
};
int init(N* n1) {
N n2(2);
cout << "pointer " << &n2 << endl;
n1->v.push_back(&n2);
};
int main() {
N n1(1);
init(&n1);
cout << n1.i << endl;
cout << "pointer " << n1.v[0] << endl;
cout << n1.v.at(0)->i << endl;
return 0;
};
The problem is that after the call to the init function, it seems that the node n2 does not exist anymore.
Thanks for your help.

Because n2 is local variable, which will be released after the init function call. Therefore after the init function call, the content reside in its previous address is undefined.
To fix this issue, consider using the new operator:
int init(N* n1) {
N* n2 = new N(2);
cout << "pointer " << n2 << endl;
n1->v.push_back(n2);
};
Or simply
int init(N* n1) {
n1->v.push_back(new N(2));
};
Since the instance you added are created by the new operator, you need to release their memory by using the delete operator (for example, in N's destructor):
~N() {
for (int i = 0; i < v.size(); ++i) {
delete v[i];
}
v.clear();
}

You need to learn about scope. n2 goes out of scope (and therefore its memory address) at the end of the function init

int init(N* n1) {
N n2(2);
cout << "pointer " << &n2 << endl;
n1->v.push_back(&n2);
} // life time of n2 ends here
n2 resides on stack. Its life time ends as soon as init returns. So having a reference to it results in undefined behavior. Try -
n1->v.push_back(new N(2));

Related

How can I access an array in another class via a pointer to that array in C++?

Usually in order to access a member variable of a class/object from a different class, you would use the arrow operator (->). In this case I would like to access an array, however the size of the array is only known at runtime, therefore I can't declare the array in the header file of the class. In fact, I only declare the array in the class constructor.
I still need to be able to access this array from a different class. I'm attempting to do this by declaring a pointer in the header file of the first class, and then after the array is declared and initialised, have that pointer point to the first element of the array.
The header file station.h:
class TokenPool {
public:
TokenPool(int K);
~TokenPool();
...
public:
int K;
int *pointToPool;
};
Then in station.cpp:
TokenPool::TokenPool(int K) {
this->K = K;
cout << "K = " << this->K << " in tokenPool" << "\n";
int pool[K];
for (int i = 0; i < K; i++) {
pool[i] = i+1;
cout << pool[i] << " tokens in class " << i << "\n";
}
pointToPool = pool;
}
For the sake of simplicity let's assume that K=1.
The problem is when I attempt to access the array from a different class like so:
cout << "class " << this->k << " has " << *(station1->tokenPool->pointToPool+0) << " tokens.\n";
It produces strange output like so:
class 0 has 31156208 tokens.
Where, if K=1, it should actually show:
class 0 has 1 tokens.
Any idea what is going on?
TokenPool::TokenPool(int K) {
...
int pool[K];
...
pointToPool = pool;
}
pool is declared on the stack, so it ceases to exist as soon as the constructor returns. You assign its address to this->pool, but the address no longer points into valid memory. Subsequently reading from this pointer results in undefined behaviour.
The C++ way is generally to avoid raw arrays, and use std::vector instead. It makes the code both simpler and safer, and hardly any less efficient:
#include <vector>
class TokenPool {
public:
TokenPool(int K);
~TokenPool();
...
public:
std::vector<int> pool;
};
TokenPool::TokenPool(int K) :
pool(K)
{
cout << "K = " << this->K << " in tokenPool" << "\n";
for (int i = 0; i < K; i++) {
pool[i] = i+1;
cout << pool[i] << " tokens in class " << i << "\n";
}
}

std::cout behaves differently when printing variable vs function expression

I'm new to c++ and I'm facing an odd behavior from std::cout that I don't understand. In particular, when I want to print the value of the second node, using cout << nd.next[2]->next[17]->val, I get some convoluted bytes. However, if I set it to a variable first, e.g string let2 = nd.next[2]->next[17]->val, then use cout << let2, it prints the correct character. My code is below, I was implementing a trie. (Also since I am very new to c++ any other comments about what I am doing wrong in the code is appreciated)
#include <iostream>
#include <set>
#include <iterator>
#include <map>
#include <string>
#include <unordered_map>
using std::set;
using std::cout;
using std::endl;
using std::string;
struct Node {
Node* next[26];
string val;
void insert(string str) {
cout << "insert " << str << endl;
insert(str, 0);
}
void insert(string str, int idx) {
if (idx >= str.length()) {
return;
}
char cur = str[idx];
int curIdx = cur - 'a';
cout << "cur: " << cur << endl;
cout << "cur idx: " << curIdx << endl;
if (!next[curIdx]) {
Node newNode = Node();
newNode.val = cur;
next[curIdx] = &newNode;
}
next[curIdx]->insert(str, idx+1);
}
};
int plus(int a, int b) {
return a+b;
}
int main() {
Node nd = Node();
nd.insert("cryptography");
string let1 = nd.next[2]->val;
string let2 = nd.next[2]->next[17]->val;
cout << "first letter " << let1 << endl; // c
cout << "second letter " << nd.next[2]->next[17]->val << endl; // wrong
cout << "second letter " << let2 << endl; // work as expected
cout << "sum " << plus(1,2) << endl; // work as expected
// cout << nd.next[2]->next[17]->val << endl;
return 0;
}
Regarding the second part of your question ("what I am doing wrong"), in the insert() method you create Node() object on stack and assign next[curIdx] with a pointer to this object. But that stack object is destroyed automatically once the execution steps out of the scope where that object is defined, so next[curIdx] ends up pointing to garbage (memory where the object used to be before destroying).
Not sure how the next line is even working, next[curIdx] points to garbage at this point: next[curIdx]->insert(str, idx+1);
Instead you should allocate Node objects on heap with the new operator, ex:
if (!next[curIdx]) {
next[curIdx] = new Node(); // allocated on heap
next[curIdx]->val = cur;
}
but then you should make sure to deallocate (delete) them at some point to avoid memory leaks. Destructor of Node may be a good place for that – you can recursively delete all non-null Nodes from next array.
Also you could use smart pointers instead of raw pointers, they automatically delete objects when they can't be no longer accessed (garbage collector does that automatically in other languages like Java and C#).
More on stack vs heap: https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

boost multiarray as class member is not filled

I'm trying to use boost to create a multidimensional array and I want said array to be a member of some class.
However I find two problems with it:
1 - I need to declare the size of the array with
boost::extents[2][2]
Everytime I want to use the array. Otherwise I get the following error:
a.out: /usr/include/boost/multi_array/base.hpp:136: Referenceboost::detail::multi_array::value_accessor_n<T, NumDims>::access(boost::type<Reference>, boost::detail::multi_array::value_accessor_n<T, NumDims>::index, TPtr, const size_type*, const index*, const index*) const [with Reference = boost::detail::multi_array::sub_array<double, 1ul>; TPtr = double*; T = double; long unsigned int NumDims = 2ul; boost::detail::multi_array::value_accessor_n<T, NumDims>::index = long int; boost::detail::multi_array::multi_array_base::size_type = long unsigned int]: Assertion `size_type(idx - index_bases[0]) < extents[0]' failed.
2 - Ok, maybe this is just part of how multidimensional arrays work in C++ with Boost, I'm going to write my code accepting every function "declares" the array. However, if I do this I find the array is empty.
Here's a snippet of code that reproduces this problem. During the "construction" of the class the array should be filled. However, the line
cout << "Result: " << testing.getArrayMember(0,1) << endl;
outputs "Result: 0".
#include <iostream>
#include "boost/multi_array.hpp"
typedef boost::multi_array<double, 2> dbl_array;
using namespace std;
class TestClass {
public:
dbl_array darray;
TestClass(double x);
void fillArray(double x);
double getArrayMember(int i, int j);
};
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
void TestClass::fillArray(double x) {
cout << "Filling array" << endl;
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
darray[0][0] = x;
darray[1][0] = 2.0*x;
darray[0][1] = 3.0*x;
darray[1][1] = 4.0*x;
cout << "Array filled" << endl;
}
double TestClass::getArrayMember(int i, int j) {
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
return darray[i][j];
}
int main() {
TestClass testing = TestClass(5.0);
// The result is 0 in the end
cout << "Result: " << testing.getArrayMember(0,1) << endl;
return 0;
}
What am I doing wrong here?
Option 1 is to use an initialisation list:
TestClass::TestClass(double x) : darray(boost::extents[2][2]) {
cout << "Class constructor called" << endl;
fillArray(x);
}
Since otherwise the member of the class darray is created using the default constructor and not through your line
dbl_array darray(boost::extents[2][2]);
as you believe.
This is the same answers as given in initialize boost::multi_array in a class
However, I want to add the following bit, which I think it is relevant in this situation:
It might be necessary for you to generate the array after performing some kind of operation in the constructor of your class. You can achieve this using "resize" after the array has been created by the default constructor.
Ie, instead of
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
you could have
TestClass::TestClass(double x) {
darray.resize(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}

accessing the member of a class of pointer array of another class

I'm trying to figure out how I can or why I can't access the member of this class. First I'll show you what works so you know what I'm thinking, then I'll show you what I can't seem to do.
What I can do is this: I have a class with a member. I make an pointer array of that class and make NEW pieces of it (through loop) and that's fine and all. I can also make another class with a similar array and even make NEW instances of that as well and initialize them, but when I try to access them, I have problems.
This code almost works fine:
#include <iostream>
using namespace std;
class testClass{
public:
int number;
};
class testPoint{
public:
testClass testInstance;
testClass *testclassArray[5];
void makeArray();
void setToI();
};
void testPoint::makeArray(){
for (int i = 0; i < 5; i++){
testclassArray[i] = new testClass;
}
}
void testPoint::setToI(){
for (int i = 0; i < 5; i++){
(*testclassArray[i]).number = i;
}
}
int main(void){
testPoint firstTestPoint;
firstTestPoint.makeArray();
firstTestPoint.setToI();
// EXCEPT FOR THIS LINE this is where I have problems
cout << firstTestPoint.(*testclassArray[0]).number << endl;
return 0;
}
I know this should work becuase this works
int main(void){
testPoint firstInstance;
firstInstance.testInstance.number = 3;
cout << firstInstance.testInstance.number << endl;
// and this works
return 0;
}
and this works
int main(void){
testClass *testPointer[5];
for (int i = 0; i < 5; i++){
testPointer[i] = new testClass;
(*testPointer[i]).number = i;
}
cout << (*testPointer[0]).number << endl;
return 0;
}
so why can't I access the members on the cout function the same way?
The following is invalid syntax:
cout << firstTestPoint.(*testclassArray[0]).number << endl;
The most common way to write what you are trying to accomplish is:
cout << firstTestPoint.testclassArray[0]->number << endl;
But, if you prefer, you can also write:
cout << (*firstTestPoint.testclassArray[0]).number << endl;
(The second way is far less common.)
The . operator is used to access members of direct objects, e.g. a.member where a might be declared as struct A a;. The -> operator is used to access members of indirect objects (aka pointers to objects), e.g. b->member where b might be declared as struct B* b = new B();.
You are dereferencing the variable in an incorrect way.
Try doing
cout << firstTestPoint.testclassArray[0]->number << endl;
instead.
In the same way the second attempt, where it works for you, could also have been written:
out << testPointer[0]->number << endl;
Try using this code:
cout << firstTestPoint.testclassArray[0]->number << endl;

Array of pointers segfault

I'm not entirely sure why I'm getting a segfault for this piece of code. I have an array of object pointers I want to create. Here is my code.
edge **test = new edge*[a]; //Edge is a predefined class I have created. a is a my size of my array.
graphCreate2(test, vertices, roads, a); //Note roads is an edge class I have already created also
However, when I try to access edge ** test's elements, I get a segfault. Here's how I accessed it.
void graphCreate2(edge **test, int vertices, edge *roads, int a)
{
for(int i = 0; i < a; i++)
{
e[i]->setEdgeSrc(roads[i].getEdgeSrc());
e[i]->setEdgeDes(roads[i].getEdgeDes());
e[i]->setLength(roads[i].getLength());
cout << e[i]->getLength() << " " << e[i]->getEdgeSrc() << " " << endl;
}
}
Might anyone know why I'm getting this segfault? I thought I allocated memory to it as the constructor is called when creating the array Thanks!
The constructor is not called for each edge. You're only creating the array of pointers, but they point to garbage.
You need to create them all in a loop.
void graphCreate2(edge **test, int vertices, edge *roads, int a)
{
for(int i = 0; i < a; i++)
{
test[i] = new edge(); // create the edge
test[i]->setEdgeSrc(roads[i].getEdgeSrc());
test[i]->setEdgeDes(roads[i].getEdgeDes());
test[i]->setLength(roads[i].getLength());
cout << test[i]->getLength() << " " << test[i]->getEdgeSrc() << " " << endl;
}
}