Different Destructor Types? - c++

I have an object called a Chunk that holds a pointer to a b2Body. It does other important things, but i removed those for simplicity. Heads up, smart pointers won't work(I think), you'll see why.
class DChunk
{
public:
DChunk();
DChunk(const DChunk& old);
virtual ~DChunk();
virtual b2Body* getBody() const;
private:
b2Body* m_pBody;//pointer;
};
The question is, how to define when to delete the m_pBody object.
If I want to copy this object, like say there is a vector of these things and I push_back another, it will call the Copy Constructor, copy the memory address of m_pBody(thats what i want), and then delete the old one. If the Destructor on this object deletes m_pBody, that's obviously bad, because the new copy wont have a valid memory address, but if it doesn't delete it, then m_pBody will never be deleted, and it needs to be deleted when there are no more Chunks pointing at it.
The only correct way to delete the m_pBody object is to call m_pBody->GetWorld()->DestroyBody( m_pBody ); and thats not under my control, so smart pointers dont really work.
I was hoping there would be different types of destructors that get called appropriately, like when a copy has been made in a vector. Also, there should never be more than one Chunk associated with one b2Body, if that is helpful.

I will assume you have something like
vector<DChunck> myvec;
and you are worried about doing
obj=DChunk()
myvec.push_back(obj)
First of all (this is very beginner friendly approach, avoiding smart pointers or any C++11) there's something not quite correct about creating a container DChunk objects. That's because when you declare
vector<DChunk>
you are telling your vector that it will receive objects the size of DChunk.
However, since that class contains a pointer to an array, m_pBody (array's size will not be constant!), this approach will not be too "healthy" for C++.
Given this, you can do something else, sticking to your class design: create a container of pointers!
You can create
vector<DChunk*> myvec;
and if you want to add an object to that vector, you just do
DChunk *obj = new DChunk();
myvec.push_back(event);
since now the container is handling pointers, which can be juggled around without interfering with the objects content, avoiding the worries concerning a destructor.
Calling an object's method will now be, for example,
(*myvec[3]).getBody()
or (cleaner version)
myvec[3]->getBody()
Hope I addressed your question

You can also provide move constructor so that instead of copying, it would move stuff... Here's an example that I made some hours ago, because I had the same problem (I didn't know in what order would these constructors and when be called, also "&&" is move constructor):
A move constructor is similar to copy constructor. The difference is that in move constructor instead of copying values and stuff, you assign given object's pointers (not copy) and values to a new one (this->temp = OldClass.temp) and then make OldClass.temp = NULL; so that when the unavoidable destructor is called, it finds a NULL pointer and does not delete it.
#include <iostream>
#include <Windows.h>
class MyClass
{
public:
MyClass()
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
}
MyClass(int x, int y)
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
temp->left = x;
temp->top = y;
}
MyClass(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
}
MyClass& operator=(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
return *this;
}
MyClass(const MyClass &OldClass)
{
*temp = *OldClass.temp;
}
MyClass& operator=(const MyClass &OldClass)
{
*temp = *OldClass.temp;
return *this;
}
~MyClass()
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
}
void Print()
{
std::cout << temp << " " << temp->left << " " << temp->top << " " << temp->right << " " << temp->bottom << '\n';
}
private:
RECT *temp;
};
int main()
{
MyClass bla, cha(54, 48);
bla.Print();
cha.Print();
bla = MyClass(2, 2);
bla.Print();
bla = cha;
bla.Print();
cha = MyClass(54, 2);
cha.Print();
std::cin.get();
return 0;
}

In common, a proper memory management is non trivial task and no universal decision are existing. Some simple and common well-known methods are presented as "smart pointer" types in newest libraries (and you can also define them yourself (by copy known "standard definition")). But it also is not an completely universal :-)
And your question seems to be a question for a such universal solution.
Some other programming languages (java ... , not C++) advertise you to get rid of that problem (by the built-in methods of language implementations).
You write: "Also, there should never be more than one Chunk associated with one b2Body, if that is helpful." . And then the problem seems to disappear (because the Chunk cannot be copied at all). (?)

Related

c++'s temporary objects when inserted to a vector

I'm trying to make this code work, but the object keep getting destroyed...
I've found that it has to do with the object being copied to the vector, but can't find any way to prevent it...
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Obje
{
private:
static int instances;
int id;
public:
static int getInstances();
void getId();
virtual void myClass();
Obje(int auxId);
~Obje();
};
int Obje::instances = 0;
int Obje::getInstances()
{
return instances;
}
Obje::Obje(int auxId)
{
this->id = auxId;
cout << "Obje Created." << endl;
Obje::instances++;
}
Obje::~Obje()
{
cout << "Obje Destroyed." << endl;
Obje::instances--;
}
void Obje::myClass()
{
cout << "Obje." << endl;
}
void Obje::getId()
{
cout << this->id << endl;
}
int main()
{
vector <Obje> list;
Obje *a = new Obje(59565);
list.push_back(*a);
Obje *b = new Obje(15485);
list.push_back(*b);
for(vector<Obje>::iterator it = list.begin(); it != list.end(); ++it)
{
it->getId();
}
return 0;
}
It Generates this output:
Obje Created.
Obje Created.
Obje Destroyed.
59565
15485
Obje Destroyed.
Obje Destroyed.
What does it mean the T(const T& new); i've saw as fix for this?
First of all, it is a bad practice to allocate an object in heap without using smart pointers and forgetting to delete it. Especially, when you are creating it just to make a copy of it.
list.push_back(*a); creates a copy of *a in vector. To create an item in vector without copying another item, you can do list.emplace_back(/*constructor parameters*/);, which is available from c++11. (see http://en.cppreference.com/w/cpp/container/vector/emplace_back)
So, to make the result behavior match your expectations, you should go
vector <Obje> vec;
vec.emplace_back(59565);
vec.emplace_back(15485);
for(const auto & item : vec)
{
item.getId();
}
By the way, it is also a quite bad practice to call a vector as a list, as a list is a different container type and reading such code may be confusing a bit. I guess, I am starting being annoying, but it is better to call method getId as showId as now it returns nothing.
Regarding the use of heap, new and pointer, see my comment in your question.
Regarding the issue object was destroyed, the vector maintains an internal buffer to store object. When you push_back new object to the vector, if its internal buffer is full, it will (the stuff which will be executed when exception occurs won't be mentioned here.):
allocate new internal buffer which is big enough to store its new data.
move data from old internal buffer to new internal buffer.
destroy old buffer.
Hence, your object will be destroyed and copied to new location in this case, hence copy constructor will make it clearer to you.
P/S: AFAIK, some compilers move its data by memmove or std::move

c++ correct deletion of structs and pointers

I have a question regarding how to correctly delete structs and it's respective pointers declared inside.
I have extracted an example from a project i have running and it doesn't seem to work correctly, the code doesn't crash but it seems i have some "memory leaks". I'm not sure that is the right wording. The issue is that the values is not really reset and are kept in the memory next time i initiate a class.
Sudocode below:
Header:
ProgramHeader.h
class ClassA : public publicClassA
{
public:
ClassA(void);
virtual ~ClassA();
private:
struct ApStruct{
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} fR;
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} f1kHz;
};
ApStruct* GetApStruct;
}
Program:
Program.cpp
#include "ProgramHeader.h"
ClassA::~ClassA()
{
//EDIT i did a typo my looks like this:
//delete ApStruct; //Wrong code
delete GetApStruct; //Corrected - however still not working
}
main()
{
GetApStruct = new ApStruct();
//Do Code
}
Hope it all makes a bit sense,
EDIT:
I have updated one wrong line in the code - however the question still remains the same. I will have a look at below to understand before i implement a solution.
EDIT 24/10/2015
I have been trying out a few of the suggestions below and im not able to find a solution to my issue, i must admit i also have difficulties to narrow it down what could cause it.
My code is part of a DLL. The code wraps some source code im not in control of, and therefore i have limited options how i init using constructors and new on pointers.
The reason i still think i have memory leak issues is if i add a "magic float" in my code the output of my functions change, even the float is not used anywhere - it is just declared.
I get different results when:
Calling InitCode - once!
then i will call CallCode multiple time - doing my calculations
Destruct the instance of the class
When i repeat the above again i get different result from the first time i run the code but afterwards it stays the same.
If i include the magic line all seems to work???
Updated SudoCode:
Program.cpp
#include "ProgramHeader.h"
ClassA::~ClassA()
{
//EDIT i did a typo my looks like this:
//delete ApStruct; //Wrong code
delete GetApStruct; //Corrected - however still not working
}
main()
{
void initCode()
{
GetApStruct = new ApStruct();
float InitValue = 0.F
//Magic line:
float magicLine = 123456.f; //If this line is commented out i get different results in my code
//End Magic Line
fr.refA[0] = &InitValue;
fr.refA[0] = &InitValue;
fr.refA[0] = &InitValue;
fr.pVarA = &InitValue;
...
}
void CallCode()
{
float CallValue = 123.F
//Magic line:
float magicLine = 123456.f; //If this line is commented out i get different results in my code
//End Magic Line
fr.refA[0] = &CallValue;
fr.refA[0] = &CallValue;
fr.refA[0] = &CallValue;
fr.pVarA = &CallValue;
...
}
}
Thanks guys for you support,
Thomas
I would recommend something like the following for allocation and cleanup...
#include <iostream>
using namespace std;
class ClassA
{
public:
ClassA(void);
virtual ~ClassA();
private:
struct ApStruct {
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} fR;
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} f1kHz;
};
ApStruct* GetApStruct;
};
ClassA::ClassA(void) {
GetApStruct = new ApStruct{};
GetApStruct->fR.refA[0] = new float{ 1.f };
GetApStruct->fR.refA[1] = new float{ 2.f };
GetApStruct->fR.refB[0] = new float{ 3.f };
GetApStruct->fR.refB[1] = new float{ 4.f };
GetApStruct->fR.pVarA = new float { 0.f };
// do same for struct f1kHz
// ...
cout << "Construction" << endl;
}
ClassA::~ClassA()
{
if (GetApStruct != nullptr) {
if (GetApStruct->fR.refA[0] != nullptr) {
delete GetApStruct->fR.refA[0];
GetApStruct->fR.refA[0] = nullptr;
}
if (GetApStruct->fR.refA[1] != nullptr) {
delete GetApStruct->fR.refA[1];
GetApStruct->fR.refA[1] = nullptr;
}
if (GetApStruct->fR.refB[0] != nullptr) {
delete GetApStruct->fR.refB[0];
GetApStruct->fR.refB[0] = nullptr;
}
if (GetApStruct->fR.refB[1] != nullptr) {
delete GetApStruct->fR.refB[1];
GetApStruct->fR.refB[1] = nullptr;
}
if (GetApStruct->fR.pVarA != nullptr) {
delete GetApStruct->fR.pVarA;
GetApStruct->fR.pVarA = nullptr;
}
// do same for struct f1kHz
// ...
// finally
delete GetApStruct;
GetApStruct = nullptr;
}
cout << "Destruction" << endl;
}
int main() {
{
ClassA a;
}
system("pause");
return 0;
}
Well when you create a structure/class object, it holds the variables and pointers in that object memory area( say an object occupies some space in memory. Let's call it a box). Those pointer variables when initialized with new() or malloc(), are given space outside of that box in which the object's data resides. Those pointers now point to some memory area that is outside of that object's memory area. Now when the object is destructed, that space occupied by object (as we called it the box) is destroyed accompanying the pointer variables. The memory area pointed by the pointers is still in there in program/process memory area. Now we have no clue what's it address or where it lies. That's called memory leak. To avoid this situation, we need to de-allocate the memory referenced by pointers using delete keyword. We're free to go now. I tried to illustrate it with a simple graphic below. ObjectA box illustrates the area occupied by it in the memory. Note that this container/box holds the local varialbes including pointer. The pointer points to some memory location, say 0xFFF... and is illustrated by green line. When we destroy ObjectA, It simply destroys everything in it including 0xFFF address. But the memory located on 0xFFF is still allocated in the memory. A memory leak.
In your destructor, de-allocate memory explicitly using delete keyword. Whoa! We saved the memory.
From Wikipedia Resource Acquisition Is Initialization
Resource Acquisition Is Initialization (RAII) is a programming idiom used prominently in C++. In RAII, resource acquisition is done during object creation, by the constructor, while resource release is done during object destruction, by the destructor. If objects are destroyed properly, resource leaks do not occur.
So you can new the memory used for pointers in constructor and release them in destructor:
ClassA::ClassA(void) {
GetApStruct = new ApStruct;
GetApStruct->fR.refA[0] = new float{ 1.f };
GetApStruct->fR.refA[1] = new float{ 2.f };
}
ClassA::~ClassA(void) {
delete []GetApStruct->fR.refA;
delete GetApStruct;
}
Alright, let me be direct:
If you are using new or delete, you are doing it wrong.
Unless you are an experienced user, or you wish to implement a low-level side project, do not ever use new and delete.
Instead, use the existing standard classes to handle memory ownership, and just avoid heap-allocation when it is unnecessary. As a bonus, not only will you avoid memory leaks, but you will also avoid dangling references (ie, using memory after deleting it).
class ClassA : public publicClassA {
public:
private:
struct ApStruct{
struct
{
float refA[2];
float refB[2];
float pVarA;
} fR;
struct
{
float refA[2];
float refB[2];
float pVarA;
} f1kHz;
};
ApStruct GetApStruct;
}
And yes, in your case it is as simple as removing the pointers. Otherwise, if you want dynamic arrays (ie, arrays whose length is unknown at compile-time) use std::vector.

Appropriate destruction of certain class members

I have a class with several pointer members that can be reallocated. When I use the LoadOBJ() function, I'm supposed to replace the already held data but I'm having trouble with garbage collection. Below is some code.
class Object3d{
public:
int nVertex;
int nFace;
int nVertexNormal;
Vector3d *vertex;
Vector3d *vertexNormal;
Face3d *face;
void LoadOBJ(char*);
Object3d():nVertex(0), nFace(0), vertex(NULL), face(NULL){}
Object3d(char*);
~Object3d(){}
};
Face3d:
struct Face3d{
int nFaceV;
int *iVertex;
int *iVertexNormal;
Face3d():nFaceV(0){}
};
Everytime I load a new object with the LoadOBJ() function, I want to delete the previously allocated memory, rather than just use new and leak previously allocated memory.
I'm not sure how to do this. This is what I thought of for now:
void *vGarbage, *vGarbage2,
*fGarbage,
*iGarbage, *iGarbage2;
//nFace is the previous number of faces; in the case of a new object, it's 0
for(int i=0; i<nFace; i++)
{
iGarbage=face[i].iVertex;
iGarbage2=face[i].iVertexNormal;
delete[] iGarbage;
delete[] iGarbage2;
}
vGarbage=vertex;
fGarbage=face;
vGarbage2=vertexNormal;
delete[] vGarbage;
delete[] vGarbage2;
delete[] fGarbage;
The above code runs everytime I use LoadOBJ(), but there still is memory leak. I'm also wondering if this is the right way to do it?
To clarify where the problem/question is: why do I still have memory leak? And, is there better/cleaner way to delete the previously allocated memory?
Check out C++11's smart_pointers, they provide the ability of allocating memory which, when the object goes out of scope, will be freed automatically.
#include <memory>
#include <iostream>
struct Foo {
Foo() { std::cout << "Foo...\n"; }
~Foo() { std::cout << "~Foo...\n"; }
};
struct D {
void operator()(Foo* p) const {
std::cout << "Call delete for Foo object...\n";
delete p;
}
};
int main()
{
{
std::cout << "constructor with no managed object\n";
std::shared_ptr<Foo> sh1;
}
{
std::cout << "constructor with object\n";
std::shared_ptr<Foo> sh2(new Foo);
std::shared_ptr<Foo> sh3(sh2);
std::cout << sh2.use_count() << '\n';
std::cout << sh3.use_count() << '\n';
}
{
std::cout << "constructor with object and deleter\n";
std::shared_ptr<Foo> sh4(new Foo, D());
}
}
Output:
constructor with no managed object constructor with object Foo... 2 2
~Foo... constructor with object and deleter Foo... Call delete for Foo
object... ~Foo...
(http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)
Remember that for each new a delete should be called when freeing memory. Local pointers can be dangerous if they get destroyed and you didn't free memory before that point.
The RAII paradigm in object-oriented C++ has been designed specifically to make resource management (and also memory management) easy.
If disaster has already been done, you can clean your code up with something like http://deleaker.com/ or equivalent memory leak-seeker software.
Also: if you can't use C++11 or you can't use a C++11-supporting compiler, take a chance of implementing smart pointers yourself, it shouldn't be too hard and will surely help your memory problems.
I understand you want to free the memory occupied by Object3d::vertex, Object3d::vertexNormal and Object3d::face before reasigning these members. First, you should provide a custom destructor for your Face3d so that you no longer need to care for it's members in the containing class. That is:
face3d::~face3d() {
if (iVertex) delete[] iVertex;
if (iVertexNormal) delete[] iVertexNormal;
}
In your Object3d class, you can use a dedicated clean-up function:
void Object3d::cleanup() {
if (face) delete[] face;
face = nullptr;
if (vertex) delete[] vertex;
vertex = nullptr;
if (vertexNormal) delete[] vertexNormal;
vertexNormal = nullptr;
nVertex = 0;
nFace = 0;
nVertexNormal = 0;
}
Btw, In the destructor Object3d::~Object3d() you must call that function as well.
This question might answer yours. I think that you have to cast the void pointer to a specific one, like int*, to make it work. But the behaviour is highly dependent of the compiler you use.
edit: the advice of using smart pointers is probably the easiest and safest way of solving your problem.
Use std::vector instead of manually managed arrays:
struct Face3d{
int nFaceV;
std::vector<int> iVertex;
std::vector<int> iVertexNormal;
Face3d():nFaceV(0){}
};
class Object3d{
public:
std::vector<Vector3d> vertex;
std::vector<Vector3d> vertexNormal;
std::vector<Face3d> face;
void LoadOBJ(char*);
Object3d():nVertex(0), nFace(0), vertex(NULL), face(NULL){}
Object3d(char*);
~Object3d(){}
};
This frees you from the burden to write destructors. As already said above, this is exemplifies the RAII pattern in C++ which should be used instead of manual resource management.
As a general comment, public data members are almost always a bad idea because it breaks encapsulation. Object3d should provide some services to clients and keep its internal private.

Why does the C++11 move constructor copy by value?

I thought the following example would have the same result as std::map::emplace(), but it didn't:
struct MoveTest {
MoveTest():
var(true)
{
cout << "ctor: " << static_cast<void*>(&var) << endl;
}
MoveTest(MoveTest&& mt):
var(std::move(mt.var))
{
cout << "move ctor: " << static_cast<void*>(&var) << endl;
}
bool var;
};
int main() {
map<int, MoveTest> mtest;
mtest.insert(make_pair(1, MoveTest()));
return 0;
}
output:
ctor: 0x7fff12e4e19b
move ctor: 0x7fff12e4e194
move ctor: 0x25f3034
The MoveTest::var has a different address in each move. It doesn't look like a "move". What's wrong in my code or understanding?
For MoveTest as you've defined it, there's not really much a move ctor (or assignment operator) can optimize (or do in general--all it can really do is copy from source go destination).
Moving is mostly a big win when an object contains a pointer to a bunch of external memory that's (for example) allocated on the heap. In this case, the move ctor/assignment operator can basically do a shallow copy (i.e., just grab the pointer from the moved-from object) instead of a deep copy (copying all the data referred to by that pointer).
For example:
class move_tst {
int *buffer;
static const int size = 1024 * 1024;
public:
move_tst() {
buffer = new int[size];
std::iota(buffer, buffer + size, 0);
}
move_tst(move_tst const &other) {
buffer = new int[size];
std::copy_n(other.buffer, size, buffer);
}
#ifdef MOVE
move_tst(move_tst &&other) {
buffer = other.buffer;
other.buffer = nullptr;
}
#endif
~move_tst() {
delete [] buffer;
}
};
Caveat: I've used a raw invocation of new and a raw pointer here so nothing else gets involved and we wouldn't (for example) get move semantics courtesy of a smart pointer. For normal code under normal circumstances, you should not be using either (raw pointer or raw invocation of new, I mean).
Edit: as far as what std::move does, it doesn't actually do a move itself--it just signals that you no longer care about a value, so it's eligible to be the source of a move, even if that destroys its value.
For example, with the class above, you could do a test like:
for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst =src;
}
...and compare it to:
for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst = std::move(src);
}
Without the std::move, dst will be created as a copy of src, but with the std::move, it'll be able to do a move from src to dst.
Your log simply tells that you create a temporary MoveTest instance with the default constructor
MoveTest()
which is then copied elsewhere, inside a pair object
make_pair(1, MoveTest())
and copied again somewhere inside the map object
mtest.insert(make_pair(1, MoveTest()));
There are three constructor invocations for three distinct MoveTest instances, each with its own address. As already well explained, whether the constructors are move constructors or old style copy constructors doesn't matter.
Did you expect some of the copies to be optimized away? With nontrivial code in the constructors it becomes unlikely; in particular, reading &var is a good reason to avoid shortcuts.

Do I have to delete this object? (if I don't intend to be ever deleted)

I have programmed a little software and wanted to create a new object on the heap. In the class member function I thus have
void gShop::CreateCustomer(int type, int number)
{
vSlot[number] = new gCustopmer(type);
vSlot[number]->itsContactToShop=itsShopNumber;
vSlot[number]->itsNumber=number;
}
where vSlot is a vector of pointers to customer objects. I have a (here: abbreviated) class gShop, in essence:
class gShop : public gBranch
{
public:
gShop(): vSlot(100){}
~gShop(){}
std::vector <gCustomer*> vSlot;
...
}
and in main I call the member function to create new customers..
vShop[0].CreateCustomer(TYPE_M20, 1);
vShop[0].CreateCustomer(TYPE_F40, **2**);//EDIT:typo previously here. I intend to create customers by reading a file later on.
std::cout<< "1" << vShop[0].vSlot[1]->itsTypeString << std::endl;
std::cout<< "2" << vShop[0].vSlot[2]->itsTypeString << std::endl;
I know that I have created with "new" two objects on the "heap" (if I handle the terminology right - sorry I am quite new to programming without formal education) and I also have two pointers to that objects stored in a vector within the object shop[0].
My question is I heard the saying that for every new there is a delete. Where do I have to delete this object? I am actually not planning on deleting any created shop or customer object in the program.
Secondly, is this code so far okay in terms of not causing memory leaks? I am a bit worried that I created the new object within a member function class, so should I try to implement delete in the destructor to gShop and set the pointer to NULL - in the theoretical case I should ever want to delete shop[0]?
Many thanks.
In the way you have written your code, you should expand you destructor implementation for gShop to iterate over the vector<> vSlot and delete each element. Because you have memory that has to be managed in this way to prevent a memory leak, you are also required to follow the Rule of Three. So, you also need to do something during copy construction (a deep copy), and you have to do something for the assignment operator (cleanup up the vector<> that is about to be copied over, and do a deep copy).
You can avoid these issues, and allow your object to use the default destructor, copy constructor, and assignment operator, by using a smart pointer instead. For example:
std::vector<std::shared_ptr<gCustomer>> vSlot;
When you create an element in the vSlot, you could use make_shared():
vSlot[number] = std::make_shared<gCustopmer>(type);
The smart pointer will delete the memory for you when there are no more references to the memory. If you don't have C++.11 available to you, you can use boost::shared_ptr instead.
The smart pointer will make it so that a copy of your gShop will share the same pointers as the original gShop it copied from. The smart pointer makes that situation okay, since there will not be multiple delete calls on the same memory. However, if you need the deep copy semantics, then you would still need to implement your own copy constructor and assignment operator to make the deep copies.
If you want something that will clean up automatically like a smart pointer, but still give you a deep copy with the default copy constructor and default assignment operator, then you can try to use boost::optional.
If you are using g++ version 4.4 or higher, then you should be able to enable C++.11 features with -std=gnu++0x, or -std=c++0x if you don't want GNU extensions. If you have g++ 4.7 or higher, then the options are -std=gnu++11 or -std=c++11.
Every time you create object with new piece of memory is taken from the heap. Only way to communicate with this memory is via pointer you got from new. When you use delete on that pointer memory is freed and may by used for other purposes. So when you lose pointer you create memory leak.
In your code the right way is:
Start with the vector with null pointers.
When you create object in exact position check pointer. If it is not null you already have object and have to delete it (or maybe throw error)
void gShop::CreateCustomer(int type, int number)
{
if(vSlot[number] != 0) {
delete vSlot[number];
vSlot[number] = 0;
}
vSlot[number] = new gCustopmer(type);
vSlot[number]->itsContactToShop=itsShopNumber;
vSlot[number]->itsNumber=number;
}
When the vector is destroyed you need to free all memory within it. So you destructor will be something like this:
gShop::~gShop() {
for(int i = 0; i < (int)vSlot.size(); ++i) {
delete vSlot[i];
}
}
Yes any memory that is allocated from the heap must be freed!
With the "new" you are allocating memory from the heap that is the sizeof gCustomer.
A good place to deallocate your memory would be in your destructor: ~gShop()
Memory leaks are caused by not deallocating your memory, although once your close your program all the memory is freed automatically.
gShop needs to delete the gCustomer objects that it creates. It can do that in its destructor, eg:
class gShop : public gBranch
{
public:
...
~gShop()
...
};
gShop::~gShop()
{
std::vector<gCustomer*>::iterator iter = vSlot.begin();
std::vector<gCustomer*>::iterator end = vSlot.end();
while (iter != end)
{
delete *iter;
++iter
}
}
Or:
void deleteCustomer(gCustomer *customer)
{
delete customer;
}
gShop::~gShop()
{
std::for_each(vSlot.begin(), vSlot.end(), deleteCustomer);
}
However, you would still have a memory leak. You are storing two separate gCustomer objects in the same vSlot[1] slot of vShop[0], so you are losing track of one of your customers. I suspect you meant to do this instead:
vShop[0].CreateCustomer(TYPE_M20, 1);
vShop[0].CreateCustomer(TYPE_F40, 2); // <-- was previously 1
std::cout<< "1" << vShop[0].vSlot[1]->itsTypeString << std::endl;
std::cout<< "2" << vShop[0].vSlot[2]->itsTypeString << std::endl;
That being said, you should re-think your design and let the STL handle all of the memory management for you, eg:
class gShop : public gBranch
{
public:
std::vector <gCustomer> vSlot;
...
};
void gShop::CreateCustomer(int type)
{
vSlot.push_back(type);
gCustomer &cust = vSlot.back();
cust.itsContactToShop = itsShopNumber;
cust.itsNumber = vSlot.size()-1;
}
vShop[0].CreateCustomer(TYPE_M20);
vShop[0].CreateCustomer(TYPE_F40);
// remember that vectors are 0-indexed
std::cout<< "0" << vShop[0].vSlot[0].itsTypeString << std::endl;
std::cout<< "1" << vShop[0].vSlot[1].itsTypeString << std::endl;
Or:
class gShop : public gBranch
{
public:
std::vector <std::shared_ptr<gCustomer> > vSlot;
...
};
void gShop::CreateCustomer(int type)
{
std::shared_ptr customer = std::make_shared<gCustomer>(type);
customer->itsContactToShop = itsShopNumber;
customer->itsNumber = vSlot.size();
vSlot.push_back(customer);
}
vShop[0].CreateCustomer(TYPE_M20);
vShop[0].CreateCustomer(TYPE_F40);
std::cout<< "0" << vShop[0].vSlot[0]->itsTypeString << std::endl;
std::cout<< "1" << vShop[0].vSlot[1]->itsTypeString << std::endl;