Using a vector data structure - design and syntax questions - c++

I have some basic C++ design/syntax questions and would appreciate your reply.
I have N number of regions
Each region needs to store information about an object "element"
i.e. I want to achieve something like this:
region[i].elements = list of all the elements for region i.
Question 1:
Does the following syntax (see code below) / design look correct. Am I missing anything here?
EDIT
The instances of struct elem are created by some other class and its memory deallocation is handles by that class only I just want to access that object and its members using reg[i].elements list (vector) ... so, how should I add these element objects to the vector "elements" in class Region?
//Already have this stucture that I need to use
struct elemt {
int* vertex;
int foo1;
double foo2;
};
class Region{
public:
// I am not sure what should be the syntax here!
// is it correct?
std::vector <elemt*> elements;
}
// Following is the constructor of "class A"
A::A(){
// --header file defines: Region *reg;
// Let numOfRegions be a class variable. ( changes based on "Mac"'s suggestion)
numOfRegions = 100;
//allocate memory:
reg = new Region[numOfRegions];
}
A::~A(){
delete [] reg;
reg = NULL;
}
A::doSomething(){
// here I want to append the elements to the vector
// Let i be region 10.
// Let e1 be an element of "struct elemt" that needs to be added
reg[i].elements.push_back(e1);
}
Question 2:
Is the syntax in doSomething() correct? Later I want to run an iterator over all the elements in reg[i] and want to access, e1->foo1, e1->foo2 and like that.
Question 3:
In do something method, how do I ensure that e1 is not already in the "elements"
UPDATE
Corrected some syntax errors, and hopefully fixed memory leak noticed by user 'Mac. '

First of all get rid of the memory leak from the code.
A::A(int numOfRegions = 100){
m_reg = new Region[numOfRegions]; // define Region *m_reg in the class
}
A::~A(){
delete [] m_reg;
m_reg = NULL;
}
You are allocating memory in the constructor and storing return address in local variable and it ll get destroyed when its scope is over .
You should store the base address so that you can delete it .

How do you know if two elements are same or not?
From your question about detecting if e1 is already there in elements, It seems like a map/set/hash might be a better data structure than a vector.
Also, I believe it is push_back, not pushBack.

You should detach the syntax from the design question. Syntax is something the compiler will check, and enforce, but then again you might get unwanted semantics...
Focusing on the design, what are your requirements? (Sorry I tend to read diagonally if there are more than a couple of lines, so I might have missed something there)
There is a class that creates/destroys elemt objects, is dynamic allocation really a requirement? or is it just because the elements are constructed with data available in the constructing class? If dynamic allocation is a requirement, then it looks like elemt objects should be held by pointer (probably smart pointers). Does the class that is meant to delete the objects keep track of them, or does it just handle the objects to the outside world expecting user code to call a deallocator function? Are the elemt objects shared among different entities? And there are other issues that you should consider...
Maybe you should try to reword your question, the code you posted basically is syntactically correct (just check with a compiler, I did not), but without knowing what you really want to achieve, you cannot really ask whether that is a good or bad design. Describe your real problem and then ask whether the code can be a solution to your requirements.

As you ask for syntax, I can spot a missing semi-colon right away.
Also, public data (such as elements) is not really recommended. Instead, try to use getter and setter functions.
The numOfRegions variable aught to be const int, not just int. Also, feels off to declare it in the c'tor instead of in the class declaration, as it is a tuneable setting. As soon as you want to iterate over reg, you'll need to redeclare it if you keep it as now.
As for question three, you will simply have to check to see if you can find it. You will probably need an bool operator==(const elemt &, const elemt &) to be able to do that conveniently.

Related

How to delete a pointer inside a struct object when the struct object goes out of scope?

I have a struct object that contains a pointer to an object.
struct Track
{
KalmanFilter* kalmanFilter; //Kalman filter for this track
....
};
I instantiate the struct and pointer objects by
Track track;
track.kalmanFilter = new KalmanFilter(contours[contour].centroid);
....
I then check each frame if the track is still valid by
//Temporary vector to hold alive tracks
std::vector<Track> tempTracks;
for(...)
{
//If track is valid save into temp tracks
if(tracks[track].deadTime <= deadTime) tempTracks.push_back(tracks[track]);
}
//Save all temp tracks back into tracks - this removes dead tracks that were in tracks
tracks = tempTracks;
After a while the micro-controller i'm using runs out of memory, this is the only pointer in my code so i'm pretty sure the KalmanFilter pointer is not being deleted.
So far I have tried a destructor in the Track struct which causes my micro-controller to hard fault immediately.
//Destructor frees up Kalman filter memory when the Track object goes out of scope
~Track()
{
if(kalmanFilter) delete kalmanFilter;
}
and I have tried using a unique_ptr but I cannot get the code to compile, all the examples I have found instantiate the object being pointed to at the same time as instantiating the unique_ptr. In my case I don't think I can do this.
What is the correct way to handle a situation like this?
Thanks
EDIT
So based on the comments there seems to be two main points.
Allocate the memory in the constructor
I have rewritten my struct to be
struct Track
{
Track(const Point& initialPosition) : kalmanFilter(initialPosition) {}
~Track() {}
KalmanFilter kalmanFilter; //Kalman filter for this track
};
and I instantiate it by
Track track(contours[contour].centroid);
Is this correct?
Find a better way to delete the tracks
What is the best way to remove an object from a vector without messing up the indexing during the loop? Using an STL iterator?
I implemented the solution from #M.M that seems to work
tracks.erase(std::remove_if(tracks.begin(), tracks.end(), [&](Track const &t){return t.deadTime > deadTime;}));
You can use a smart pointer:
struct Track
{
std::unique_ptr<KalmanFilter> kalmanFilter;
....
};
This means that when the Track is destroyed, if the smart pointer is managing a pointer it will invoke delete on that pointer.
It could be assigned by:
track.kalmanFilter.reset(new KalmanFilter(contours[contour].centroid));
although it'd be preferable to have this done by the constructor of Track.
This change will render Track non-copyable (but still movable). This is a good thing because previously your code did not behave properly on being copied anyway, so now the compiler will catch it for you.
You will need to modify your erase-loop to stop making copies of the elements. The normal way to do this is to use vector::erase combined with std::remove_if (the latter moves the selected elements to the end, and erase erases elements off the end):
tracks.erase( std::remove_if( begin(tracks), end(tracks),
[&](Track const &t) { return t.deadTime > deadTime; } ), end(tracks) );
Required includes would be <memory> and <algorithm>.
The way you are eliminating dead tracks will cause many copies of each track to be made.
The destructor to one of your many copies will try to deallocate that memory while active copies are still using that kalman filter which can cause issues. Also, if you can't guarantee it is NULL before being assigned... could be a random pointer being deleted.
In this situation I'd use a shared pointer. But to be honest, I feel like there is a better overall structure for how you are storing/using the tracks, I'd have to think about it and know more about the implementation though.
When you do push_back() you are creating a copy of the original Track object. Both the copy and the original object point to the same memory, and both at some point get destructed resulting in a double deallocation of the same address. Following the suggestions in the comments on better code organization will help avoid such bugs.

Is it possible to assign a memory location to a class variable?

Lets say I have a class "ClassA". Is it possible to assign a pointer of another instance of the class to a non-pointer variable? for example
ClassA pineapple();
ClassA* replacementPineapple = new ClassA();
pineapple.refersto = replacementPineapple; <- something like that
The reason I'm asking is because I have a class where I need to move a lot of the class variables to be physically located in a memory mapped file. I could of course just have them as pointers and dereference them every time i need to use them but thats a lot of dereferencing and with all the brackets and other stuff just makes the code really hard to read. If there is any way around that I'll take it.
Yes it is. You can allocate the memory flat and then do the copying (from an existing object) by hand. Or you use placement new operator to allocate/construct at a given location.
see: using placement new
I need to move a lot of the class variables to be physically located in a memory mapped file. I could of course just have them as pointers and dereference them every time i need to use them but thats a lot of dereferencing and with all the brackets and other stuff just makes the code really hard to read. If there is any way around that I'll take it.
class ClassA
{
public:
ClassA(int* p_a, double* p_d) : a_(*p_a), d_(*p_d) { }
int& a_;
double& d_;
};
Then you can create an instance like this:
ClassA my_a(ptr_to_a_in_shmem, ptr_to_d_in_shmem);
And write code (member functions or otherwise) that opererates on a_ and d_ thereby accessing/modifying shared memory.
If I understand your question correctly you just want to use pineapple as an alias for *replacementPineapple. You can do this by first creating the latter, and defining pineapple to be of reference type (marked by &)
ClassA* replacementPineapple = new ClassA();
ClassA& pineapple = *replacementPineapple;
Now every (read or write) access to a member of pineapple will actually access the corresponding member of *replacementPineapple. Only if you should at some time modify the pointer replacementPineapple to point elsewhere (or become null) then pineapple will still refer to the object it originally pointed to, and there is no way you can make it follow.

C++ function call with type pointer, parameter confusion: incomplete type is not allowed

I'm trying to wrap my head around C++. I'm going to just give you tiny pieces to help illustrate the idea without making things to convoluted. Btw, im only implementing these methods, i cannot change the setup or parameters.
I have a class for a dynamic array data structure that holds objects called stocks:
typedef class Stock ArrayType;
class DynamicArray {
ArrayType** items;
int numberOfElements;
...
}
Here's its constructor. I'm supposed to allocate the array and add one item, then set the number of elements.
DynamicArray::DynamicArray(ArrayType* const item){
Stock *items = NULL; // ... i guess? pointers to pointers confuse me
// now im guessing i need to create a actual stock array and point the above pointer to it
items = new Stock[1]; // ERROR: incomplete type is not allowed? I've tried several things, and cant get rid of the red squiggles
this->numberOfElements = 1;
}
Okay, there are a few problems. Off the bat, you have to include Stock first. The compiler needs the full definition of Stock before it can compile DynamicArray, because of memory allocation by my guess.
Secondly, you want the items member-value to contain the reference to the array created in the constructor. So instead of defining Stock *items[1] in the constructor, assign the value of the new statement directly to this->items; you can ommit this-> as long as you don't define a variable with the same name in whatever function you're working on.
Finally, you're allocating an array of pointers, so you use this syntax: new ArrayType*[1]
Additionally, just as a coding-practices point, you shouldn't mix the use of typedefs and their original types in the same source. So I'd recommend you use ArrayType throughout or not at all.

When making an instance with shared_ptr, what should happen with the pointer instance variables?

Alright, here I have this small example of my complex class
class LivingObject
{
Ogre::SceneNode* myNode;
Gorilla::ScreenRenderable* myScrRend;
Gorilla::Layer* myRendLayer;
Gorilla::Rectangle* myRendRect;
int Health,Energy,Strength,Dexterity,Intelligence;
float Speed,posX,posY,posZ;
//Assortment of functions
};//Note: Specific members and functions are public/private, but is not relevant
Here is some game class info
class myGame
{
Ogre::Viewport* myViewport;//random
LivingObject LiveObjectArray[100]//question 1: holds the array of objects from a parsed file
std::vector<std::tr1::shared_ptr<LivingObject> > spawnList;//question 2
};
1) How should I be declaring LivingObject where I can copy it later(the current method I am using gives an error: conversion from 'LivingObject*' to non-scalar type 'LivingObject' requested)LivingObject TestObj=new LivingObject;
1a) What do I do with pointers like LivingObject::myNode when making a new object, should I make them objects? or is something else wrong?(Note: I am using Ogre3D and this is the way that the tutorials made me set everything...)
2) When the above is solved, how would I then put it into a shared_ptr vector and access that specific element for functions(e.g. spawnList[15].(or ->)Attack(target);
1) In order to copy an object, use this code:
string s;
string t = s;
1a) What do those pointers represent? If they represent exclusive ownership, you must copy the objects they point to when copying the owning object. Check any good text's introduction to constructors and destructors. Consider making the LivingObject class non-copyable.
2) Try this:
shared_ptr<T> p(new T);
vector<T> v;
v.push_back(p);
...
shared_ptr<T> q = v[0];
q->member_function();
As a last advise, you need a good C++ book. Another great resource is an online community of other users like this one here. If possible, try to reduce your code though. It's enough that LivingObject has one example pointer. Good luck!

Trying to store an object in an array but then how to call that object's methods?

I'm not a very experienced c++ coder and this has me stumped. I am passing a object (created elsewhere) to a function, I want to be able to store that object in some array and then run through the array to call a function on that object. Here is some pseudo code:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
I know the object is passing correctly, because the first call to object.action() does what it should. But when I store object in the array, then try to invoke action() it causes a big crash.
Likely my problem is that I simply tinkered with the .'s and *'s until it compiled, T[0].action() compliles but crashes at runtime.
The simplest answer to your question is that you must declare your container correctly and you must define an appropriate assigment operator for your class. Working as closely as possible from your example:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
Note the signature change to const reference which emphasizes that we are going to copy the original object and not change it in any way.
Also note carefully that arrayFromElsewhere[0].action() is NOT the same as objInstance.action() because you have made a copy — action() is being invoked in a different context, no matter how similar.
While it is obvious you have condensed, the condensation makes the reason for doing this much less obvious — specifying, for instance, that you want to maintain an array of callback objects would make a better case for “needing” this capability. It is also a poor choice to use “T” like you did because this tends to imply template usage to most experienced C++ programmers.
The thing that is most likely causing your “unexplained” crash is that assignment operator; if you don't define one the compiler will automatically generate one that works as a bitwise copy — almost certainly not what you want if your class is anything other than a collection of simple data types (POD).
For this to work properly on a class of any complexity you will likely need to define a deep copy or use reference counting; in C++ it is almost always a poor choice to let the compiler create any of ctor, dtor, or assignment for you.
And, of course, it would be a good idea to use standard containers rather than the simple array mechanism you implied by your example. In that case you should probably also define a default ctor, a virtual dtor, and a copy ctor because of the assumptions made by containers and algorithms.
If, in fact, you do not want to create a copy of your object but want, instead, to invoke action() on the original object but from within an array, then you will need an array of pointers instead. Again working closely to your original example:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
Note closely that arrayFromElsewhere is now an array of pointers to objects instead of an array of actual objects.
Note that I dropped the const modifier in this case because I don’t know if action() is a const method — with a name like that I am assuming not…
Note carefully the ampersand (address-of) operator being used in the assignment.
Note also the new syntax for invoking the action() method by using the pointer-to operator.
Finally be advised that using standard containers of pointers is fraught with memory-leak peril, but typically not nearly as dangerous as using naked arrays :-/
I'm surprised it compiles. You declare an array, objectList of 8 pointers to T. Then you assign T[0] = object;. That's not what you want, what you want is one of
T objectList[8];
objectList[0] = object;
objectList[0].action();
or
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
Now I'm waiting for a C++ expert to explain why your code compiled, I'm really curious.
You can put the object either into a dynamic or a static array:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
This doesn't really make a lot of sense, though; you would usually have defined your array somewhere else, outside the function.