Creating c++ vector of pointers - c++

In my C++ code I have a class Object equipped with an id field of type int. Now I want to create a vector of pointers of type Object*. First I tried
vector<Object*> v;
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
but this failed because here the same address just repeats itself n times. If I used the new operator I would get what I want but I'd like to avoid dynamic memory allocation. Then I thought that what I need is somehow to declare n different pointers before the for loop. Straightforward way to this is to declare an array so I did this :
vector<Object*> v;
Object ar[n];
for(int i=0; i<n; i++) {
ar[i] = Object(i);
}
for(int i=0; i<n; i++) {
v.push_back(ar+i);
}
Is there still possibility to get a memory leak if I do it this way? Also going through an array declaration is a bit clumsy in my opinion. Are there any other ways to create vector of pointers but avoid manual memory management?
EDIT: Why do I want pointers instead of just plain objects?
Well I modified the original actual situation a bit because I thought in this way I can represent the question in the simplest possible form. Anyway I still think the question can be answered without knowing why I want a vector of pointers.
Actually I have
Class A {
protected:
vector<Superobject*> vec;
...
};
Class B: public A {...};
Class Superobject {
protected:
int id;
...
}
Class Object: public Superobject {...}
In derived class B I want to fill the member field vec with objects of type Object. If the superclass didn't use pointers I would have problems with object slicing. So in class B constructor I want to initialize vec as vector of pointers of type Object*.
EDIT2
Yes, it seems to me that dynamic allocation is the reasonable option and the idea to use an array is a bad idea. When the array goes out of scope, things will go wrong because the pointers in vector point to memory locations that don't necessarily contain the objects anymore.
In constructor for class B I had
B(int n) {
vector<Object*> vec;
Object ar[n];
for(int id=0; id<n; id++) {
ar[id] = Object(id);
}
for(int id=0; id<n; id++) {
v.push_back(ar+id);
}
}
This caused very strange behavior in objects of class B.

In this loop:
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
You are creating n times Object instance on stack. At every iteration there is created and removed element. You can simply avoid this using that:
for(int id=0; id<n; id++) {
Object* ob = new Object(id);
v.push_back(ob);
}
thanks that every new element exist on heap not on the stack. Try to add to in class Object constructor something like that:
std::cout<<"Object ctor()\n";
and the same in the destructor:
std::cout<<"Object dtor()\n";
If you dont want to create these objects with "new" try reason written by #woolstar

Your question about memory leaks makes me think you are worried about the lifecycle and cleanup of these objects. I originally proposed shared_ptr wrappers, but C++11 gave us unique_ptr, and C++14 filled in the missing make_unique. So with all that we can do:
vector<unique_ptr<SuperObject>> v ;
Which you create in place with the wonderfulness of perfect forwarding and variadic templates,
v.push_back( make_unique<Object>( ... ) ) ;
Yes you are going to have to live with some heap allocations, but everything will be cleaned up when v goes away.
Someone proposed a boost library, ptr_container, but that requires not only adding boost to your project, but educating all future readers what this ptr_container is and does.

No there is no memory leak in your version. When the program leaves your scope the vector as well the array are destroyed. To your second question: Why not simply store the objects directly in an vector?
vector<Object> v;
for(int i = 0; i < n; i++)
{
Object obj = Object(i);
v.push_back(obj);
}

Related

Order of destructors

I have these kind of classes:
Game:
class Game {
private:
BoardField*** m_board_fields;
public:
Game() {
m_board_fields = new BoardField**[8];
for (int i = 0; i < 8; i++) {
m_board_fields[i] = new BoardField*[8];
}
}
Game::~Game() {
for (int i = 0; i < 8; i++) {
for (int j = 0; i < 8; j++) {
delete m_board_fields[i][j];
}
delete[] m_board_fields[i];
}
delete[] m_board_fields;
}
}
BoardField:
class BoardField {
private:
ChessPiece* m_piece;
....
public:
BoardField::~BoardField() {
delete m_piece;
}
}
And on the close of the program I get error in ~BordField:
Exception thrown: read access violation.
this was 0xFDFDFDFD.
Did I made my destructors incorrect? What is the best way to clear memory from multidimensional array ?
There is are two fundamental flaws in your design:
there is no clear ownership of the BoardFields: someone create it, someone else deletes it. It can work if you're very cautious but it's error prone.
you do not ensure the rule of 3 (or better 5): if you have any piece of code where you create a copy of either your Game or a of any BoardField the first object that gets destroyed will delete the m_piece pointer, and when the second object gets destroyed, it'll try to delete a second time the same pointer, which is UB.
There is a third important issue: you're over-using raw pointers:
if m_board_fields is a 2d array of fixed size, make it a fixed size array (aka BoardField* m_board_fields[8][8]). If you want to keep its size dynamic, use vectors.
a cell of m_board_field could be a pointer if there's some polymorphism expected. But this seems not the case here, as obviously ChessPiece is the polymorphic class. So better use plain fields instead of pointers (aka BoardField m_board_fields[8][8]).
Finally, instead of using raw pointer to ChessPiece, better use a shared_ptr<ChessPiece> : you don't have to worry about shallow pointer copies and double delete; the shared_ptr will take care of itself and destroy the object if it's no longer used.

Do I need to call delete[] on a member array that is declared with a constant value in class decleration?

here is an example of a code hopefully will demonstrate my confusion
#define MAX_LENGTH 5
class Bar
{
private:
Foo *_myFooArray[MAX_LENGTH];
public:
Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
_myFooArray[i] = new Foo(i);
}
}
};
Since I am not creating the array with new I don't think I can use delete[] but what if I want to delete the objects that are allocated dynamicly? do I iterate through the array and delete them one at a time? as such;
~Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
delete _myFooArray[i];
}
}
I will probably hear some of you screaming at me Use Vectors!! I appreciate that. I just want to learn. Just for completeness, If for some reason I have to use the array as mentioned above, are there anything that I need to pay extra attention besides deleting the array correctly?
One of the rules in C++ when not using smart pointers is "every new needs a delete."
You must use the destructor from your question to avoid leaking memory. The array itself is not allocated using new so you do not need to delete it.
No, you do not delete [] the array. The array is part of your instance's data. The elements you allocate specifically are not, so you should delete them.

creating an initialization and deleting function for a c++ multi-dimensional pointer to class

I created a class and using multi-dimensional pointer as follows:
variable **v_mod;
v_mod = new variable *[3];
for(int i=0;i<3;i++)
{
v_mod[i] = new variable [n];
}
and deleting pointer after using
for( int i = 0 ; i < 3 ; i++ )
{
delete [] v_mod[i];
}
delete [] v_mod;
This is working perfectly fine but I am using many pointers. So can anyone help in writing a function in the class which helps in creating and deleting the pointers like
variable ** v_mod;
v_mod.create(3,n);
v_mod.delete();
and which works same way?
Don't use new use a vector:
vector<vector<variable>> v_mod(3, vector<variable>(n));
This will require that your variable object has a generated or your own default constructor.
But other than that you can use the vector version of v_mod as you used the dynamically allocated array version, except that a vector cleans itself up when it goes out of scope. So no need to delete.
EDIT:
#Hamza Anis has asked me how to do this without vector, so I'm updating this answer to reflect a couple ways to do that. Let me preface this by saying, vector is the right way to do this, anything short of vector is simply making life harder on everyone who handles the code.
Option 2 unique_ptr:
unique_ptr<variable[]> v_mod[3];
for(auto& i : v_mod) {
i = make_unique<variable[]>(n);
}
Option 3 only do this if it's a homework assignment:
variable* v_mod[3];
for(auto& i : v_mod) {
i = new variable[n];
}
for(auto& i : v_mod) {
delete[] i;
}
[Complex Example using ints]

Creating unknown number of objects with each having specific object name at runtime c++

I want to create an unknown number of objects each with a specific object name inside the main-method at runtime. The objects should be existent until the program ends (main-method ends). Note, that in my case the objects are Fields.
I thought about a solution like this:
for ( i=1 ; i <= NumberOfObjects ; i++)
{
if (i==1)
{
MyClass *ObjectName1 = new MyClass();
}
if (i==2)
{
MyClass *ObjectName2 = new MyClass();
}
. //more if statements for more objects
.
.
} //for loop closed
Questions:
I don't think this solution is good, since the number of created objects still would be limited to the if-statements within the for-loop. Any better solutions?
Scope of pointers in loops: When the if-blocks are exited the pointers are out of scope. How can I access the with "new" created objects afterwards?
Named variables are removed once the code is compiled and doesn't mean anything to you afterwards.
Looks like you need a look up table, use an std::map or std::unordered_map with string key as the name of the object.
std::map<std::string, MyClass*> variablesTable;
for ( i=1 ; i <= NumberOfObjects ; i++)
{
std::ostringstream oss << "name" << i;
variablesTable[oss.str()] = new MyClass(); //you actually need to check if it exists, otherwise will be overwritten.
}
As if you want each created to run a separate code for each object, you can have a table of function objects (or just store both in a tuple) like this std::map<std::string, std::<MyClass, Func>>.
If you want to lookup just use,
MyClass* object = variablesTable[strName];
object->CallFunction();
P.S. A known trick for hash_maps is to run script before building the project to convert any literal string to int, because comparing int is faster than strings. At least I know this was used in the Uncharted series (but hardly relevant to your case).
To elaborate on your approach, there is no need for a loop. You can simplify this to
MyClass *ObjectName1 = new MyClass();
MyClass *ObjectName2 = new MyClass();
MyClass *ObjectName3 = new MyClass();
...
The scope and the lifetime of the pointer already ends, when you leave the if statement. To access the pointers outside the if/for statements, you have to move them before the loop.
I would just use a std::vector of objects
std::vector<MyClass*> objects;
for (int i = 1; i <= NumberOfObjects; i++) {
MyClass *p = new MyClass();
objects.push_back(p);
}
This won't give you an individual name for each object, but is maintainable at least.
Update:
To address the concerns of leaking memory, you can also create the objects directly in the vector without an explicit new
std::vector<MyClass> objects;
for (int i = 1; i <= NumberOfObjects; i++)
objects.push_back(MyClass());
This will give you the objects and they will be cleaned automatically, when the scope of the vector ends.
You will need something to store that objects. For example you could use a std::vector, or a std::map. You can store an unlimited number of objects (actually you're limited by your memory amount, let's say almost unlimited) inside these data structures, without caring about the memory since it's managed automatically.
EDIT: OK, that's not an answer. OP wants arbitrary object count at run time!
That question may be a template meta programming one.
Use a vector to store the pointer, use a macro to define a new pointer and push it to the vector.
Before ending, use the vector to free.
#include <vector>
#define DEFVAR( varname ) \
foo* varname = new foo(); \
v.push_back( varname )
class foo {};
int main() {
std::vector<foo*> v;
DEFVAR( ObjName1 );
DEFVAR( ObjName2 );
DEFVAR( ObjName3 );
DEFVAR( ObjName4 );
[ .... ]
for ( size_t index = 0; index < v.size(); ++index ) delete v[ index ];
return 0;
}

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