maps initialization in c++ for implementing tries - c++

I am trying to implement tries in c++. Here is the structure I have used:
typedef struct tries{
int wordCount;
int prefixCount;
map<int,struct tries*> children;
}tries;
The initialize method:
void initialise(tries *vertex)
{
vertex = (tries*)malloc(sizeof(tries*));
vertex->wordCount = vertex->prefixCount = 0;
for(char ch='a';ch<='z';ch++)
vertex->children[ch]=NULL;
}
The initialize method has segmentation fault at vertex->children[ch]=NULL; The fault is:
Program received signal SIGSEGV, Segmentation fault.
0x000000000040139a in std::less<int>::operator() (this=0x604018,
__x=#0x21001: <error reading variable>, __y=#0x7fffffffddb8: 97)
at /usr/include/c++/4.6/bits/stl_function.h:236
236 { return __x < __y; }
What is wrong?

You should not use malloc() if you are working with C++. Also, you should not allocate enough memory to hold a pointer (sizeof(tries*)) if you need to create an object the size of a tries.
Use the new operator:
vertex = new tries();
Or even better, do not use new at all and avoid doing manual memory management with raw pointers, new, and delete. Consider using smart pointers instead.
Also, in C++ classes have constructors, so the initialise() method could actually be replaced by a constructor for tries:
struct tries
{
tries() : wordCount(0), prefixCount(0)
{
// ...
}
int wordCount;
int prefixCount;
map<int, struct tries*> children;
};

Related

I get an error when trying to make a vector of classes inside of the same class

I am trying to make a class with decendants of the same class, to make a tree, but when i try to access something insode of the vector it never works. i get an exception: std::length_error when trying to access the string.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
string name;
vector<A*> children;
};
int main()
{
A cl;
cl.name= "HI!";
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
for(int i = 0; i < 10;i++) {
// error here:
cout << cl.children[i]->name << endl;
}
return 0;
}
Anybody know an easier way to make a tree in C++, or how to fix this?
The problem is in this loop
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
The variable newCl will cease to exist at the end of the iteration and you are inserting its address in the vector. When you access it, you are accessing a dangling pointer, this is undefined behavior and your program can crash, produce garbage or anything in between.
You can use heap allocation as proposed by Oblivion, but in such a case you might want to consider the use of smart pointers for memory management.
Otherwise, you can have a vector of values std::vector<A> instead of pointers, possible from C++17 (for more details, see: How can I declare a member vector of the same class?)
Edit: I clarified the use of std::vector<A> after Chipster's comment.
You store reference to a temporary as children:
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
Once you are out of scope the children will dangle.
A* newCl = new A;
Should fix. But you have to go through the vector to free your children.
If you had a reason to use pointers, it is better to use smart pointers:
vector<shared_ptr<A>> children;
Live

do I HAVE to use the new keyword?

This isn't the code I'm working on but it's the gist of what I want to do.
object *objects; int totalObjects;
void addObject(object o)
{
objects[totalObjects] = o;
totalObjects++;
}
It's giving me an access error when I try this:
Unhandled exception at 0x00e8a214 in crow.exe: 0xC0000005: Access violation writing location 0xcccccccc
Am I going to have to use 'new' and if so do I have to create a new array to copy to every time? Can I just add or take elements from the array I'm using?
Why don't you just use std::vector?
std::vector<object> objects;
void addObject(object o)
{
objects.push_back(o);
}
..or
void addObject(const object &o)
{
objects.push_back(o);
}
to remove additional copying.
When it comes to implementing your own dynamic array without std::vector, Yes. you need to allocate new memory, and copy your array to new memory block. Here's my example code with malloc and placement new.
#include <stdlib.h> // for malloc/free
#include <new> // for placement new, std::bad_alloc
object *objects = nullptr;
size_t totalObjects = 0;
void addObject(const object &o)
{
object *old_objects = objects;
size_t old_size = totalObjects;
size_t new_size = totalObjects + 1;
object *new_objects = (object *)malloc(sizeof(object) * new_size);
if (new_objects == nullptr)
throw std::bad_alloc();
size_t i;
try
{
for (i = 0; i < old_size; ++i)
{
new (&new_objects[i]) object(old_objects[i]); // placement new
}
}
catch (...)
{
// destroy new_objects if an exception occurs during creating new_objects
for (size_t j = 0; j < i; ++j)
{
new_objects[i].~object();
}
free(new_objects);
throw;
}
objects = new_objects;
free(old_objects);
}
(I haven't tested the code yet >o<)
Note that I used malloc and placement new, not new operator. It's impossible to call copy constructor of each element of the dynamic array with array-new.
However, if your object is TriviallyCopyable, you can use realloc. It can be more efficient, because realloc can just expand memory block, without copying - if the memory is enough.
..And you can select multiple lines and just press TAB in Visual Studio (..or many other editors).
You declared an object pointer, but not yet allocated the actual memory to store object objects. Your assignment statement merely tries to copy the input object o into an unallocated array member.
This is why you should use new before the assignment. The new operator asks the system to allocate some memory in the required size, then return the address of that memory and assign it to the pointer. Then, the pointer points to that newly allocated memory and the assignment (or copying) can be made.
When you finished using the array space, you should free the allocated memory using delete.
Okay, I'm going to add an answer to my own question. Let me know if this is bad etiquette. I just wanted to post some of my own code to duel with yours.
#include <vector>
std::vector<object> objects;
okay so I want to have two arrays (vectors) for the objects and double for distances so I may end up with
std::vector<double> distances;
void swap(unsigned int a, unsigned int b)
{
objects.swap_ranges(a,b);
distances.swap_ranges(a,b)
}
I'm going by the cplusplus.com reference for this function so let me know if I have it wrong. I'm going to go through it and completely redo my code.
Is there a type like the matrix that will let me hold data of different types so I don't have to invent a new object to handle each one individually?
If what you wrote is the most efficient and fast way to do this then I'll make a new class to hold both items.
thanks :)

Using "new" operator to create objects in an array C++

In Java
nodes[i] = new Object();
is a valid statement
What is the C++ equivalent?
EDIT:
It seems I am not providing enough context.
I was reading some Java code implementing a QuadTree, and I was curious on how I could rewrite that segment of code in C++.
I did not need a direct equivalent, I wanted something that essentially means the same thing.
In Java, you can do things like
class A
{
public A (someObject o);
}
main method:
A aObject = new A(new someObject());
or in a loop:
for(int i = 0; i < arr.length; i++)
{
arr[i] = new someObject();
}
In C++ I know you can do:
std::vector<someObject*> arr;
someObject* o = new someObject;
arr.push_back(o);
Is there something similar to java's new Object(); style of creating objects without explicit declaration in C++?
Java is a garbage-collected language, while C++ is not. The languages differ so much on what the code above "means", that it is not trivial to quote a direct "equivalent".
A similar method of implementing this in C++, would be to use shared_ptr, which is not garbage collected, but instead ensures that the underlying objects are destroyed when all references to them go out of scope.
#include <vector>
#include <memory>
using namespace std;
class Object
{
};
int main()
{
std::vector<std::shared_ptr<Object>> nodes(1);
nodes[0] = std::make_shared<Object>();
return 0;
}
There are actually a few aspects regarding your question, depending on what do you really mean by the piece of code you posted.
1. Explicit command
Yes, this command can be issued in C++, for example:
class Object
{
};
int main(int argc, char * argv[])
{
std::vector<Object *> nodes;
nodes.push_back(nullptr);
int i = 0;
nodes[i] = new Object();
// To prevent memory leaks
delete nodes[i];
}
2. Using generic base class, Object
C++ does not have a universal base class such as Object in Java or C#. You have to instantiate something to put it into the array or std::vector. (read more: Root base class in C++)
If you really need such class in your code, you can simply define one, for example:
class Object
{
virtual std::string ToString()
{
return "Object";
}
virtual int GetHashCode()
{
return (int)this;
}
virtual bool Equals(Object & other)
{
return this == &other;
}
};
3. Memory management
In C++ you can explicitly instantiate class at some point.
However, C++ does not have garbage collector working for the dynamic objects such as Java or C#. If you allocate memory explicitly using new operator, you have to delete allocated memory at some point.
On the other hand, C++ tries lately to catch up to high-level languages by providing a set of classes simplifying memory management, such as std::shared_ptr, std::weak_ptr or std::unique_ptr, for example:
class Object
{
};
int main(int argc, char * argv[])
{
std::vector<std::unique_ptr<Object>> nodes;
nodes.resize(1);
int i = 0;
nodes[i] = std::unique_ptr<Object>(new Object());
// nodes destructor will call std::unique_ptr<Object>
// destructor, which will eventually destroy instance
// of the Object class.
}
Read more here: What is a smart pointer and when should I use one?
4. Indexing arrays, classes
You can always use [] to index arrays. You may use [] to index class instances (such as std::vector) if class supports that (overloads [] operator).
int main(int argc, char * argv[])
{
// Statically allocated array
int test[5];
test[0] = 1;
// Dynamically allocated array
// This is useful if you work with
// some C libraries or simply (really)
// need to allocate a block of memory.
int * test2 = new int[5];
test2[0] = 1;
delete[test2];
// This is a lot more C++ way of keeping
// an array of items:
std::vector<int> test3;
test3.resize(1);
test3[0] = 1;
}

Best Methods for Dynamically Creating New Objects

I'm looking for a method to dynamically create new class objects during runtime of a program. So far what I've read leads me to believe it's not easy and normally reserved for more advanced program requirements.
What I've tried so far is this:
// create a vector of type class
vector<class_name> vect;
// and use push_back (method 1)
vect.push_back(*new Object);
//or use for loop and [] operator (method 2)
vect[i] = *new Object;
neither of these throw errors from the compiler, but I'm using ifstream to read data from a file and dynamically create the objects... the file read is taking in some weird data and occasionally reading a memory address, and it's obvious to me it's due to my use/misuse of the code snippet above.
The file read code is as follows:
// in main
ifstream fileIn
fileIn.open( fileName.c_str() );
// passes to a separate function along w/ vector
loadObjects (fileIn, vect);
void loadObjects (ifstream& is, vector<class_name>& Object) {
int data1, data2, data3;
int count = 0;
string line;
if( is.good() ){
for (int i = 0; i < 4; i++) {
is >> data1 >> data2 >> data3;
if (data1 == 0) {
vect.push_back(*new Object(data2, data3) )
}
}
}
}
vector<Object> vect;
vect.push_back(Object()); // or vect.emplace_back();
That's it. That is the correct way, period. Any problems you are describing with reading objects from a file are a seperate matter, and we'd need to see that code in order to help you figure out what is wrong.
If you need polymorphism, then use a smart pointer:
vector<unique_ptr<Base>> vect;
vect.emplace_back(new Derived);
If you are, for some reason, constrained from using smart pointers, the old fashioned, error prone way to do it is like this:
vector<Base *> vect;
vect.push_back(new Derived);
....
for (int i=0; i<vect.size(); ++i)
{
delete vect[i];
vect[i] = NULL;
}
This is, of course, not exception safe.
If you absolutely have to use pointers (your objects store large data sets internally) then you should change your code to:
// create a vector of type class
vector<class*> vect;
// and use push_back (method 1)
vect.push_back(new Object);
//or use for loop and [] operator (method 2)
vect[i] = new Object;
Keep in mind that you'll have to delete your objects at some point.
vector<classType> vect;
declares vector container which contains type of classType, but you are adding a pointer to classType into vect, which will make compiler unhappy indeed.
If you need to present object's polymorphism in vector container, you need to store pointer to object, change your vect type to:
vector<std::shared_ptr<classType> > vect;
Declaring dynamic objects uses the following format:
TypeName * Name = new TypeName
you're going a little to fast with your vector, what you need to do is create a new object of class Object, THEN push it into the vector.
Object * MyObj = new Object //allocate space for new object
vect.push_back(MyObj) //push back new object
REMEMBER to delete what ever you allocate, which means looping through each element at the end to delete its member:
for(int i = 0; i < vectLen; i++) //probably will be replaced with iterators for vectors
{
delete vect[i];
}
read up on dynamic allocation more in depth here

Would this be considered good C++ code

I have a vector with raw pointers (no, I cannot use smart pointers) and I want to add items to the list in a for loop. I've made a little trial project, and I wondered if this is considered good C++ code in terms of pointer management.
Please only consider raw pointer management, I am not interested in smart pointers for this particular problem I'm trying to solve.
A simple object:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
EDIT:
So the problem I am trying to solve is adding the DOMNode* to a vector from this library.
I'm starting to get the feeling that trying to write a wrapper for the parts I need from this library for my project, is a bad idea. Or maybe the library is no good?
I haven't got it to work properly using smart_ptr, if anybody out there has, then I'd like to hear about it.
Well, this leaks memory, so it is bad. Can you use a Pointer Container?
The reason this code leaks is because you create objects on the heap using new, but you never call delete on them.
As for you comment, if you have an object that manually manages some resource, you need The Big Three.
I'll consider that you have a loop, at the end of the method, to call delete on each member of the vector.
There are still issues, specifically exception safety issues.
If anything throws between the creation of the Request and its registration in the vector, you've lost the memory. One solution is to temporarily use a scoped_ptr to hold on the memory, push_back with ptr.get() and then call the release method since now the memory is owned by the vector.
If anything throws between the point when you have created the items in the vector and the point you destroy them, you need to catch the exception, destroy the items, and then rethrow.
There might be others, but RAII has been invented for a reason, it's really difficult to do without (correctly...)
If you cannot use smart pointers, then use boost::ptr_vector.
Note that if you are using TinyXml, memory management in XmlNode is probably dictated by the library - recent history iirc is that many of your problems are associated with properly understanding the memory ownership and release paradigm for this library.
What memory management do I need to cleanup when using TinyXml for C++?
What is the best open XML parser for C++?
If you are not able (or allowed) to use smart pointers, probably you could make use of a simple memory manager like this:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
A quick improvement could be to derive a class RequestVector from std::vector<Request*>, add a ClearRequests method (which deletes all the Request objects and clears the vector) and and make it's destructor call ClearRequests.
(Actually aggregating the vector in RequestVector could be a better choice, but a derived class is faster done).