convert malloc to new c++ for struct - c++

I have this struct:
struct problem
{
int length;
struct node **x;
};
and I created a struct of this struct like this:
struct problem prob;
I can do this in C:
prob.x = Malloc(struct node *,prob.length);
but how I can do it in c++ style with new ? and why ?

In C++, it would be achieved with this.
std::vector<node *> problem(length);
The code you show is effectively emulating a small subset of the features of vector. Namely, an array-like container that is aware of its size.

Ok, this code might work, note that you are no longer holding a pointer to a pointer, but a simple array - which may or may not work for what you are trying to do:
typedef struct tagnode
{
...
} node;
typedef struct tagproblem
{
int length;
node *x;
tagproblem(int len) : length(len)
{
x = new node[length];
}
~tagproblem()
{
delete [] x;
}
} problem;
//Now create...
problem = new problem(2);

Related

Difference Between "struct Obj* obj" and "Obj* obj"

struct Element{
Element() {}
int data = NULL;
struct Element* right, *left;
};
or
struct Element{
Element() {}
int data = NULL;
Element* right, *left;
};
I was working with binary trees and I was looking up on an example. In the example, Element* right was struct Element* right. What are the differences between these and which one would be better for writing data structures?
I was looking up from this website:
https://www.geeksforgeeks.org/binary-tree-set-1-introduction/
In C, struct keyword must be used for declaring structure variables, but it is optional(in most cases) in C++.
Consider the following examples:
struct Foo
{
int data;
Foo* temp; // Error in C, struct must be there. Works in C++
};
int main()
{
Foo a; // Error in C, struct must be there. Works in C++
return 0;
}
Example 2
struct Foo
{
int data;
struct Foo* temp; // Works in both C and C++
};
int main()
{
struct Foo a; // Works in both C and C++
return 0;
}
In the above examples, temp is a data member that is a pointer to non-const Foo.
Additionally, i would recommend using some good C++ book to learn C++.
In C++, defining a class also defines a type with the same name so using struct Element or just Element means the same thing.
// The typedef below is not needed in C++ but in C to not have to use "struct Element":
typedef struct Element Element;
struct Element {
Element* prev;
Element* next;
};
You rarely have to use struct Element (other than in the definition) in C++.
There is however one situation where you do need it and that is when you need to disambiguate between a type and a function with the same name:
struct Element {};
void Element() {}
int main() {
Element x; // error, "struct Element" needed
}

Difficulties about structure and pointers in C

I'm currently facing some problems accessing a double pointer.
1. The double pointer that is an element of a structure.
2. The double pointer is also instance of another structure.
3. That structure also contains an element that is explicitly a char type variable declared by typedef.
For example.
The main structure is this.
typedef struct SomeOne
{
NodeT **aOthers;
int height;
} SomeOne;
NodeT is defined as below:
typedef struct NodeT
{
NodeItemT info;
} NodeT;
NodeItemT is defined as below:
typedef char NodeItemT;
Now from the main function I want to add a value to the
NodeT **aOthers;
I have to declare SomeOne structure as follow:
SomeOne* somePerson;
Now from somePerson if I've to store a value to the "**aOthers" what I've to do?
To add a value I've a function defined as this:
void padd(SomeOne *somePerson, NodeItemT item);
Now can anyone please help me to define this function?
Here are your types:
typedef char NodeItemT;
typedef struct
{
NodeItemT info;
} NodeT;
typedef struct
{
NodeT **aOthers;
} SomeOne;
Here's how you can access them:
SomeOne so;
NodeT* others = new NodeT();
so.aOthers = &others;
(*so.aOthers)->info = 'A';
Does aOthers have to be a pointer to a pointer?

Deleting new structs in C++

I have buggy behaviour in C++ code that seems to be caused by the incorrect freeing of dynamically created structs. The structs are in the form:
typedef struct
{
char *value;
} Element;
typedef struct
{
int num;
Element **elements;
int *index;
} Container;
They are created like this:
Element *new_element(int size)
{
Element *elem = new Element;
elem->value = new char[size];
return elem;
}
Container *new_container(int num)
{
Container *cont = new Container;
cont->num = num;
cont->elements = new Element*[num];
cont->index = new int[num];
}
What is the correct way to free these?
You can easily fix all freeing problems by outsourcing resource management to the compiler:
#include <cstdlib>
#include <string>
#include <vector>
struct Element {
Element() = default;
explicit Element(std::size_t size) : value(size, '\0') { }
std::string value;
};
struct Container {
explicit Container(std::size_t size) : elements(size), index(size) { }
std::vector<Element> elements;
std::vector<int> index;
};
For all your future resource management problems, see The Definitive C++ Book Guide and List.
You should be doing this a sensible way. As others have pointed out, it can be made automatic. Failing that you should clean up in destructors. Failing that, however, and to answer the actual question, the syntax for deleting a new array is:
int x = new x[20];
delete [] x;
You will of course have to delete everything you new, so you will need to loop through the elements deleting each one in turn before deleting the elements array itself. You'd think someone would have wrapped that up in a convenience type cough vector cough.

Pointer to a C++ structure

If I create a structure in C++ like this:
typedef struct node {
int item;
int occurrency;
};
I know that a structure is allocated in memory using successive spaces, but what is the name of the structure (node in this example)? A simple way to give a name to the structure?
In C++ you don't have to use typedef to name a structure type:
struct node {
int item;
int occurrency;
};
is enough.
A pointer to an instance of that struct would be defined as node* mypointer;
E.g: You want to allocate a new instance with new:
node* mypointer = new node;
In C
struct node {
int item;
int occurrency;
};
is a tag, and by itself, it doesn't represent a type.
That is why you cannot do
node n;
You have to do
struct node n;
So, to give it a "type name", many C programmers use a typedef
typedef struct node {
int item;
int occurrency;
} node;
That way you can do
node n;
Instead of
struct node n;
Also, you can omit the tag and do the following
typedef struct {
int item;
int occurrency;
} node;
However, in C++ this all changes, the typedef syntax is no longer needed. In C++ classes and structs are considered to be user-defined types by default, so you can just use the following
struct node {
int item;
int occurrency;
};
And declare nodes like this
node n;
node is the name of the type. You can have multiple objects of that type:
struct node {
int item;
int occurrency;
};
node a;
node b;
In this example, both a and b have the same type (==node), which means that they have the same layout in memory. There's both an a.item and a b.item.

Using C++ to make a generic type - a template with shared implementation

As an example, consider a simple data structure like a linked list. In C, it might look like:
struct Node
{
struct Node *next;
void *data;
};
void *getLastItem(struct Node*);
...
I'd like to have the same struct and functions, but with better type checking by declaring the type of the data field, which will always be a pointer to something. An example use:
Node<Thing*> list = getListOfThings();
Thing *t = list->data;
t = getLastItem(list);
...
But I don't want to generate an implementation for every type of pointer, as happens with a normal template. In other words, I want something more like a generic or parametric type from Java, ML, and other languages. I just tried the code below as a test. The untyped C-like part would eventually go in a implementation file, while the template and function declarations would be in the header file. I'm assuming they would be optimized away and I'd be left with machine code that is about the same as the C version, except it would be type-checked.
But I'm not great with C++... Is there a way to improve this, or use more idiomatic C++, perhaps template specialization?
#include <stdio.h>
struct NodeImpl
{
NodeImpl *next;
void *data;
};
void *getLastItemImpl(NodeImpl *list)
{
printf("getLastItem, non-template implementation.\n");
return 0; // not implemented yet
}
template <typename T>
struct Node
{
Node<T> *next;
T data;
};
template <typename T>
T getLastItem(Node<T> *list)
{
return (T)getLastItemImpl((NodeImpl*)list);
}
struct A { };
struct B { };
int main()
{
Node<A*> *as = new Node<A*>;
A *a = getLastItem(as);
Node<B*> *bs = new Node<B*>;
B *b = getLastItem(bs);
}
This is exactly what Boost.PointerContainer does, check its implementation. Basically what it does is implement the specialization for void*, and have any other implementation forward to it static_casting the parameters in and out.
struct Node
{
struct Node *next;
void *data;
};
void *getLastItem(struct Node*);
...
This is common for C, but not for C++. In C++ it usually looks like this:
template<typename T>
struct Node
{
struct Node *next;
T data;
};
T& getLastItem(const Node&);
...
Note the important difference -- the C version has another level of indirection in order to share implementations, while the C++ version need not do this. This means the C version has another n dynamic memory allocations, where n is the number of items in the list. Given that each allocation usually requires obtaining a global lock, often has at least 16 bytes of overhead per allocation, as well as all the overhead the memory manager brings to the party, the advantage of the C++ version is not insignificant, particularly when you include things like cache locality in the considerations.
Put another way, for Node<int>, the C++ version stores an int, while the C version stores an int *, along with a dynamic allocation for the int.
This of course discounting that a linked list is a horrendous data structure 90% of the time.
If you must use a linked list, and if you must use dynamic allocation for the data members, then your idea of "replace the pointers with void*s" is not unreasonable. However, if you have access to a C++11 compiler (VS2010, recent GCC versions, etc.), you should put in an assert that you depend on T being a pointer type, using std::is_pointer and static_assert, and you should use static_cast rather than C-style casts in your interface methods. The C style cast would let someone do Node<SomeTypeBiggerThanVoidPtr>, and it would compile, but explode at runtime.
As the other answers and comments said, use std::forward_list, or another existing library. If you refuse, this is more like I would do:
#include <stdio.h>
struct NodeImpl
{
NodeImpl *next;
void *data;
public:
// we have pointers, so fulfill the rule of three
NodeImpl() : next(NULL), data(NULL) {}
~NodeImpl() {}
NodeImpl& operator=(const NodeImpl& b) {next = b.next; data = b.data; return *this;}
// This function now a member. Also, I defined it.
void* getLastItem()
{
if (next)
return next->getLastItem();
return data;
}
void* getData() {return data;}
void setData(void* d) {data = d;}
};
// the template _inherits_ from the impl
template <typename T>
struct Node : public NodeImpl
{
Node<T> operator=(const Node<T>& b) {NodeImpl::operator=(b);}
// we "redefine" the members, but they're really just wrappers
T* getLastItem()
{ return static_cast<T*>(NodeImpl::getLastItem());}
T* getData() {return static_cast<T*>(NodeImpl::getData());}
void setData(T* d) {NodeImpl::setData(static_cast<void*>(d));}
//or, if you prefer directness...
operator T*() {return static_cast<T*>(NodeImpl::getData());}
Node<T> operator=(T* d) {NodeImpl::setData(static_cast<void*>(d));}
};
struct A { };
struct B { };
int main()
{
Node<A> as; //why were these heap allocated? The root can be on the stack
A *a = as.getLastItem();
Node<B> bs; //also, we want a each node to point to a B, not a B*
B *b = bs.getLastItem();
B* newB = new B;
bs = newB; //set the data member
newB = bs; //read the data member
}
http://ideone.com/xseYk
Keep in mind that this object doesn't encapsulate next or data really, so you have to manage all of that yourself.