I'm trying to speed up a python routine by writing it in C++, then using it using ctypes or cython.
I'm brand new to c++. I'm using Microsoft Visual C++ Express as it's free.
I plan to implement an expression tree, and a method to evaluate it in postfix order.
The problem I run into right away is:
class Node {
char *cargo;
Node left;
Node right;
};
I can't declare left or right as Node types.
No, because the object would be infinitely large (because every Node has as members two other Node objects, which each have as members two other Node objects, which each... well, you get the point).
You can, however, have a pointer to the class type as a member variable:
class Node {
char *cargo;
Node* left; // I'm not a Node; I'm just a pointer to a Node
Node* right; // Same here
};
Just for completeness, note that a class can contain a static instance of itself:
class A
{
static A a;
};
This is because static members are not actually stored in the class instances, so there is no recursion.
No, but it can have a reference or a pointer to itself:
class Node
{
Node *pnode;
Node &rnode;
};
Use a pointer, & better initialized:
class Node {
char * cargo = nullptr;
Node * left = nullptr;
Node * right = nullptr;
};
Modern C++
It is a better practice to use smart-pointers (unique_ptr, shared_ptr, etc.), instead of memory allocations by 'new':
#include <string>
#include <memory> // For 'std::unique_ptr'
class Node {
public:
std::string cargo;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
int main()
{
auto bt = std::make_unique<Node>();
(*bt).cargo = "Coffee";
(*bt).left = std::make_unique<Node>();
}
Related
I'm new to C++. I am initializing a class object Node in another class LCache. When I try to compile my code, I get the following error:
Line 22: Char 5: error: unknown type name 'left'
left -> next = right;
^
Below is the code I have written:
class Node{
public:
int k;
Node* prev;
Node* next;
Node (int key){
k=key;
prev=NULL;
next=NULL;
}
};
class LCache {
private:
Node* left = new Node(0);
Node* right = new Node(0);
left -> next = right;
right -> prev = left;
...
When I move left -> next = right; and right -> prev = left; inside a method in class LCache, the error goes away. Can you explain the reason here?
You can't perform non-declaration statements inside of a class declaration, like you are trying to do. You need to perform them inside of a class member function instead, or in this case inside of the class constructor (like you did with Node), eg:
class Node{
public:
int k;
Node* prev;
Node* next;
Node (int key){
k = key;
prev = NULL;
next = NULL;
}
};
class LCache {
private:
Node* left = new Node(0);
Node* right = new Node(0);
LCache() {
left->next = right;
right->prev = left;
}
~LCache() {
delete left;
delete right;
}
...
};
That being said:
NULL is deprecated in modern C++, use nullptr instead.
And you should use smart pointers whenever you have owned pointers that need freeing when they are done being used. Or better, just don't use objects dynamically when you don't actually need to.
Try something more like this instead:
class Node{
public:
int k;
Node* prev = nullptr;
Node* next = nullptr;
Node (int key) : k(key) {}
};
class LCache {
private:
std::unique_ptr<Node> left = std::make_unique<Node>(0);
std::unique_ptr<Node> right = std::make_unique<Node>(0);
LCache() {
left->next = right;
right->prev = left;
}
...
};
/* alternatively:
class LCache {
private:
Node left{0};
Node right{0};
LCache() {
left.next = &right;
right.prev = &left;
}
...
};
*/
You're trying to do an assignment in the declaration of the class type. That makes no sense!
You probably wanted to write things such as "assign to left's next field the value…" in some method of your code.
This far, this is plain invalid C++ – maybe go a little slower in your C++ intro. The step from "I write a C++ class and assign values to its fields" to "I build a graph" is non-negligible.
I'm trying to speed up a python routine by writing it in C++, then using it using ctypes or cython.
I'm brand new to c++. I'm using Microsoft Visual C++ Express as it's free.
I plan to implement an expression tree, and a method to evaluate it in postfix order.
The problem I run into right away is:
class Node {
char *cargo;
Node left;
Node right;
};
I can't declare left or right as Node types.
No, because the object would be infinitely large (because every Node has as members two other Node objects, which each have as members two other Node objects, which each... well, you get the point).
You can, however, have a pointer to the class type as a member variable:
class Node {
char *cargo;
Node* left; // I'm not a Node; I'm just a pointer to a Node
Node* right; // Same here
};
Just for completeness, note that a class can contain a static instance of itself:
class A
{
static A a;
};
This is because static members are not actually stored in the class instances, so there is no recursion.
No, but it can have a reference or a pointer to itself:
class Node
{
Node *pnode;
Node &rnode;
};
Use a pointer, & better initialized:
class Node {
char * cargo = nullptr;
Node * left = nullptr;
Node * right = nullptr;
};
Modern C++
It is a better practice to use smart-pointers (unique_ptr, shared_ptr, etc.), instead of memory allocations by 'new':
#include <string>
#include <memory> // For 'std::unique_ptr'
class Node {
public:
std::string cargo;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
int main()
{
auto bt = std::make_unique<Node>();
(*bt).cargo = "Coffee";
(*bt).left = std::make_unique<Node>();
}
I have a class called Node:
class Node {
private:
Node right;
Node left;
std::string value;
public:
Node(Node right, Node left, std::string value) {
this->right = right;
this->left = left;
this->value = value;
}
};
And I need to declare a private variable of type Node inside the Node class itself.
Is there any way to do this?
You must declare the members as being pointers to Node instances. Especially since you want to be able to set them to NULL, which can only be done with pointers:
class Node {
private:
Node* right;
Node* left;
std::string value;
public:
Node(Node* right, Node* left, std::string value) {
this->right = right;
this->left = left;
this->value = value;
}
};
When you are trying to declare a class with itself as a member like this, you need to use pointers to do so. If you didn't need pointers, then creating one node object would construct two node members, both of which have their own node members which would construct more nodes and so on. By using pointers, you effectively must explicitly link each pointer member to an object in the heap, which prevents an immediate stack overflow error.
class Node {
private:
Node* right;
Node* left;
std::string value;
public:
Node(Node right, Node left, std::string value) {
this.right = new Node(right.data);
this.left = new Node(left.data);
this.value = value;
}
~Node(){ delete left; delete right; }
};
Here's an example of how this might look. This won't compile as-is, but its a representation of the right idea. Make sure to initialze left or right to nullptr unless you explicitly assign it in construction and specify a destructor like in this example. Also don't forget "the big three" if needed.
Note that I changed your shorthand to a dot operator, as in this.right. Your compiler will probably understand what you mean, but the shorthand should only be used when accessing a pointers data, such as in something like right->data. In case you didn't know, right->data actually does the exact same thing as (*right).data. We use a shorthand operator because *right.data would fail because the dot operator has higher precedence than the dereference operator.
I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.
As you can see in the following code, I attempt to have some default arguments of the function "initialize" that are union. How to change the definition of the function "initialize" to make it compatible with C++ before C++ 11? Do I need to add some constructors to RedBlackPointer? If so, how?
template <typename T> class RedBlackNode{
protected:
union RedBlackPointer{
RedBlackNode *node;
struct{
unsigned value:1; // for color / other info
}flag;
}left, right, parent;
T key;
public:
void initialize(T key, RedBlackPointer left = {(RedBlackNode*)0},
RedBlackPointer right = {(RedBlackNode*)0},
RedBlackPointer parent = {(RedBlackNode*)0}){
this->key = key;
this->left = left; this->right = right;
this->parent = parent;
}
}
Indeed, the extended initialization lists are not available before C++11.
As long as you keep in mind that only ONE member in a union can be active at any time, you can easily solve the issue with a default constructor:
template <typename T> class RedBlackNode{
protected:
union RedBlackPointer{
RedBlackPointer() : node(0) { } // <==== default constructor
RedBlackNode *node;
struct{
unsigned value:1; // for color / other info
}flag;
}left, right, parent;
T key;
public:
void initialize(T key, RedBlackPointer left = RedBlackPointer(), //refer to default ctor
RedBlackPointer right = RedBlackPointer(),
RedBlackPointer parent = RedBlackPointer()){
this->key = key;
this->left = left; this->right = right;
this->parent = parent;
}
void show() {
cout<<left.node<<","<<right.node<<","<<parent.node<<","<<key<<endl;
}
}; // <=== ;
And here how to demonstrate that it works:
RedBlackNode<int> N;
N.initialize(5);
N.show();
Here a live demo and here with a compiler that rejected your initial code.
Additional comment:
One thing puzzles me: in your union you combine a pointer with a one bit flag.
This is not shoking per se: it could imagine it being a trick to avoid overhead of pointer allocation, when sometimes the value poitned to is small enough to be stored directly in the tree.
However in this case, it's not clear how you will know wich is the active member (i.e. when to use the pointer, and when to use the flag is used).
So I'd suggest you cross check that there is not a mistake / forgottoen element here.