Dynamic Polymorphism and Dynamic Memory Allocation - c++

Is it always necessary to allocate memory from the heap to facilitate dynamic polymorphism? All the examples i've come across so far point to the same.
Dynamic memory allocation is usually avoided in real-time-programming.So,is there any disadvantage of using the stack for dynamic polymorphism as shown in the code below.
class Base
{
public:
virtual void Display()= 0;
};
class Derived:public Base
{
public:
void Display()
{
cout << "In derived" << endl;
}
};
int main()
{
Base* base;
Derived derived1;
base = &derived1;
base->Foo();
return 0;
}

A better example would be:
void func(Base &base);
int main()
{
Derived derived;
func(derived);
return 0;
}
The use of polymorphism doesn't have to be near where the object is created on the stack.
A lot of our unit-testing code these days looks roughly like:
void test()
{
MockObject mockObj;
RealObject objectToBeTested(mockObj);
// Do tests
}
This depends intimately on polymorphism, but creates objects on the stack.

You don't have to use the heap if you want to use polymorphism, as you pointed out in your question. But you often have no other choice. Small contrived example:
void doSomething(int what) {
// figure out which implementation to create
Base * b;
if(doA) {
b = new ConcreteA; // 1a
} else if(doB) {
b = new ConcreteB; // 1b
}
...
b->...; // 2
}
You can't use the stack, because at the moment you know what to do, 1a and 1b, every storage you get from the stack will be reclaimed when that scope is left again. You have to use the heap because you need some storage that lasts that local scope.
Some libraries advertise with them being able to not use the heap, but still behave polymorphic. They usually do that with placement new:
void doSomething(int what) {
// allocate form *the stack*, outside the if blocks, so this
// storage lasts until the function returns
char buffer[MAX(sizeof (ConcreteA), sizeof(ConcreteB))];
if(doA) {
new (buffer) ConcreteA; // 1a
} else if(doB) {
new (buffer) ConcreteB; // 1b
}
Base *b = static_cast<Base*>(static_cast<void*>(buffer));
b->...; // 2
}
The new calls in 1a and 1b now use the buffer created on the stack as the storage for the created object. So, no heap memory allocation is required anymore. That form of allocation has the main disadvantage that it's currently not possible in C++ to tell whether the buffer is correctly aligned for the types ConcreteA and ConcreteB though. So, it can be that the array is aligned on a 2 byte boundary, but the objects are required to be created on a 4 byte boundary, resulting in undefined behavior when you try to create those objects into that buffer.
Boost.Function is one of those libraries that use such a placement new approach to create objects of polymorphic types without using heap allocation using a small buffer (hence, what it does is called small buffer optimization).

There's no problem with using the stack.
When you're using the stack then you often know exactly what type of object it is ... so there's no need for the method to be virtual, it's harmless but unnecessary, for example:
Derived derived;
derived.Foo();
However, the object (which exists on the stack) can be passed to subroutines which accept a superclass instance as a parameter (in which case the fact that it's a subclass is useful/used):
void foo(Base* base)
{
...
}
void test()
{
Derived derived;
foo(&derived);
}

I think this is perfectly fine. The only possible drawback is the limited scope of an object created on the stack, but that's not necessarily related to polymorphism.

Using the stack will be fine for the simple case you show. One real time issue with dynamic polymorphism vs static is the added time to to go through the indirection of the method call. Which is an extra memory access per method call.
You need to explain more about what your doing to analyze other factors, e.g. is the stack frame guaranteed to be in physical memory, sharing, number of instances, lifespan of instances

Related

Bypassing constructor in C++

I am attempting to use C++ for AVR programming using gcc-avr. The main issue is that there is no libc++ available and the implementation does not define any of the new or delete operators. Similarly there is no header to include using placement new is not an option.
When attempting to allocate a new dynamic object I am tempted to just do this:
Class* p = reinterpret_cast<Class*>(malloc(sizeof(Class)));
p->Init();
where Init() manually initializes all internal variables. But is this safe or even possible?
I have read that object construction in C++ is somewhat complex but without new or delete how do I initialize a dynamically allocated object?
To expand on the above question.
Using standard g++ and placement new it is possible to subvert constructors in two ways, assuming that C++ uses the same straightforward ways of alligning memory as C (code example below).
Using placement new to initialize any allocated memory.
Initialize allocated memory directly using class methods.
Of course this only holds if the assumptions are true that:
Memory layout of an object is fixed at compile time.
Memory allocation is only concerned with class variables and observers normal C rules (allocated in order of declaration aligned to memory boundary).
If the above holds could I not just allocated memory using malloc and use a reinterpret_cast to convert to the correct class and initialize it manually? Of course this is both non-portable and hack-ish but the only other way I can see is to work around the problem and not use dynamically allocated memory at all.
Example:
Class A {
int i;
long l;
public:
A() : i(1), l(2) {}
int get_i() { return i; }
void set_i(int x) { i = x; }
long get_l() { return l; }
void set_l(long y) { l = y; }
};
Class B {
/* Identical to Class A, except constructor. */
public B() : i(3), l(4) {}
};
int main() {
A* a = (A*) ::operator new(sizeof(A));
B* b = (B*) ::operator new(sizeof(B));
/* Allocating A using B's constructor. */
a = (A*) new (a) B();
cout << a->get_i() << endl; // prints 3
cout << a->get_l() << endl; // prints 4
/* Setting b directly without constructing */
b->set_i(5);
b->set_l(6);
cout << b->get_i() << endl; // prints 5
cout << b->get_l() << endl; // prints 6
If your allegedly C++ compiler does not support operator new, you should be able to simply provide your own, either in the class or as a global definition. Here's a simple one from an article discussing operator new, slightly modified (and the same can be found in many other places, too):
void* operator new(size_t sz) {
void* mem = malloc(sz);
if (mem)
return mem;
else
throw std::bad_alloc();
}
void operator delete(void* ptr) {
free(ptr);
}
A longer discussion of operator new, in particular for class-specific definitions, can also be found here.
From the comments, it seems that given such a definition, your compiler then happily supports the standard object-on-heap creations like these:
auto a = std::make_shared<A>();
A *pa = new A{};
The problem with using Init methods as shown in the code snippet in your question is that it can be a pain to get that to work properly with inheritance, especially multiple or virtual inheritance, at least when something during object construction might throw. The C++ language has elaborate rules to make sure something useful and predictable happens in that situation with constructors; duplicating that with ordinary functions probably will get tricky rather fast.
Whether you can get away with your malloc()-reinterprete_cast<>-init() approach depends on whether you have virtual functions/inheritance. If there is nothing virtual in your class (it's a plain old datatype), your approach will work.
However, if there is anything virtual in it, your approach will fail miserably: In these cases, C++ adds a v-table to the data layout of your class which you cannot access directly without going very deep into undefined behavior. This v-table pointer is usually set when the constructor is run. Since you can't safely mimic the behavior of the constructor in this regard, you must actually call a constructor. That is, you must use placement-new at the very least.
Providing a classless operator new() as Christopher Creutzig suggests, is the easiest way to provide full C++ functionality. It is the function that is used internally by new expressions to provide the memory on which the constructors can be called to provide a fully initialized object.
One last point of assurance: as long as you do not use a variable length array at the end of a struct like this
typedef struct foo {
size_t arraySize;
int array[];
} foo;
the size of any class/struct is entirely a compile time constant.

C++: Inside a method can one create an uninitialised object from the class?

Inside a method can one create an uninitialised object from the class?
Here's some context: imagine a class where the constructors all allocate memory:
class NumberArray
{
size_t m_Size;
int *m_Numbers;
public:
NumberArray() { m_Size = 1; m_Numbers = new int[1]; m_Numbers[0] = 0; }
// . . . other methods for manipulating or constructing . . .
~NumberArray() { delete[] m_Numbers; }
// What if I had a method that concatenates two arrays?
NumberArray ConcatenateWith(const NumberArray &) const;
};
Inside such a method one would desire to create an uninitialised object of class NumberArray, and then 'construct' a new object based on this and the object in the parameter? AKA:
NumberArray NumberArray::ConcatenateWith(const NumberArray &other) const
{
// Mystery manner of creating an uninitialised NumberArray 'returnObject'.
returnObject.m_Size = m_Size + other.m_Size;
returnObject.m_Numbers = new int[returnObject.m_Size];
std::copy(m_Numbers, m_Numbers + m_Size, returnObject.m_Numbers);
std::copy(other.m_Numbers, other.m_Numbers + other.m_Size, returnObject.m_Numbers + m_Size);
return returnObject;
}
What's the best way of doing this? Basically, I don't want the default constructor to create a size 1 array that I will just delete and then allocate a new array for again anyway.
It's not entirely clear what you are trying to do, but if all you want is to create a new instance of the class and not have a constructor other than the default constructor called then do just that.
All you have to do is create a private constructor, that has a different signature from the default constructor and which does not allocate memory (or differs in whatever way you need it to differ from the default constructor); then simply have your class invoke that constructor internally, when necessary.
What you're asking for is placement new. This looks something like this:
#include <cstdlib>
#include <new>
void* mem = std::malloc(sizeof(T)); // memory for a T (properly aligned per malloc)
T* x = new (mem) T; // construct a T in that memory location
x->~T(); // destruct that T
std::free(mem); // and free the memory
Doing this correctly (in an exception-safe manner with properly managed and aligned memory) is not a trivial task. You need to be careful about the lifetime of your objects.
For your question, you are describing exactly what std::vector does. It allocates raw uninitialized memory and constructs inserted elements directly into that memory. And lots of its code is dedicated to just getting the lifetime and memory management correct and exception safe!
You should strongly prefer to use std::vector instead of writing it yourself.
There is no well-defined way, as far as I'm aware, to create an object without invoking it's constructor. This is regardless of whether you have access to its public interface or not, though you could implement a private or protected constructor if you want to restrict who can invoke it. There is otehrwise no restrictions on creating new instances of a class from its own internal methods, in fact it is quite common to define a private constructor and a static public method that create instances of said object if you want to restrict under which conditions said object can be created.
If you want to, you can allocated sufficient memory for an object and reinterpret_cast a pointer to that memory to a pointer of the type you want. This usually works for POD's, but since many implementations (if not all) of polymorphic inheritance in c++ adds a pointer to a vtable to polymorphic instances this approach will usually, if not always, fail for those.
In short, create a private constructor and have a static method invoke it and then do any other work that you need is my recommendation.
I think this may be similar to what you want, an 'anonymous' class of sorts:
struct test {
virtual void doSomething() {
puts("test");
}
};
struct a {
test *t() {
struct b : test {
void doSomething() {
puts("b");
};
};
return new b;
};
};
int main()
{
a a;
a.t()->doSomething(); // outputs 'b'
}
However, due to slicing and how new works on C++, you must return a pointer and the 'anonymous' type must have a name, even if it's restricted only to the function.
If you could edit the OP and clarify exactly what you wish to accomplish by this, maybe we could help you more.

Instantiate a class on stack, where var is defined in header

I am currently trying to get into writing proper C++ code (getting it running was ok for some small prototypes, but it's been ugly).
I recently realized the difference of heap and stack instantiation (O m = new O() vs. O m()).
Now I have a class, where the header file defines a variable, which holds an table definition.
ChunkLoader.hpp:
TablePartion *tablePartial_;
ChunkLoader.cpp:
ChunkLoader() { tablePartial_ = new TablePartial(true, 0, 1); }
Now I want to instantiate the tablePartial on the stack, but I cannot use:
TablePartial tablePartial_(true, 0, 1);
I am totally blind? How can I allocate tablePartial_ on the stack?
Or I am getting it totally wrong, and I cannot use in the constructor since it would be out of scope after the constructor and thus be freed? But since I read that stack variables are better performance-wise, I'd like to use stack instantiation (and getting red of delete).
Main reason: stack overflow told me to get rid of pointers when ever possible. :)
To start off, you should probably avoid the terms "on the stack" or "on the heap", they're implementation details that have nothing to do with the concepts being discussed. Instead, we discuss the lifetime of the object, in terms of automatic (which more or less correlates with the stack), dynamic (which more or less correlates with the heap), static (which more or less correlates with globals), and thread (which is a thread-specific global).
In answer to your specific question, you can use constructor initializers to initialize your variable:
ChunkLoader()
: tablePartial_(true, 0, 1)
{
}
Since the class declaration is:
class MyClass
{
SomeOtherClass x;
};
x is contained in MyClass completely (it's not a pointer to SomeOtherClass).
Ergo, when creating an object MyClass on the stack, x will also be on the stack, and when creating an object MyClass on the heap, x will also be on the heap.
EDIT:
As I understood it, you want to allocate x on the stack. To do this, any instance of MyClass must also be on the stack. For this, you can make the new operator private:
class MyClass
{
SomeOtherClass x;
private:
void* operator new(size_t);
};
If you haven't used the word "new" in C++ (avoiding malloc and other C/OS calls for this conversation), then you haven't dynamically allocated memory on the "heap".
Everything you create in main() and the functions called therein goes on the stack if new isn't used. When you enter a new function call, you get a new stack frame, and all variables declared as so:
void foo() {
int x;
std::string y;
}
are created on the stack.
You can even get a "pointer" to a stack based object so you can use it polymorphically just like a pointer to a heap object:
//These should be "classes" with private/public hiding but I'm being lazy.
struct MyClass {
int x;
virtual void foo();
};
//These should be "classes" with private/public hiding but I'm being lazy.
struct MyClassDerived : MyClass {
void foo() { std::cerr << "foo called!" << std::endl; }
};
int main() {
MyClassDerived x;
MyClass* = &x;
x->foo();
}

C++ virtual function table memory cost

Consider:
class A
{
public:
virtual void update() = 0;
}
class B : public A
{
public:
void update() { /* stuff goes in here... */ }
private:
double a, b, c;
}
class C {
// Same kind of thing as B, but with different update function/data members
}
I'm now doing:
A * array = new A[1000];
array[0] = new B();
array[1] = new C();
//etc., etc.
If i call sizeof(B), the size returned is the size required by the 3 double members, plus some overhead required for the virtual function pointer table. Now, back to my code, it turns out that 'sizeof(myclass)' is 32; that is, I am using 24 bytes for my data members, and 8 bytes for the virtual function table (4 virtual functions). My question is: is there any way I can streamline this? My program will eventually use a heck of a lot of memory, and I don't like the sound of 25% of it being eaten by virtual functions pointers.
The v-table is per class and not per object. Each object contains just a pointer to its v-table. So the overhead per instance is sizeof(pointer) (usually 4 or 8 bytes). It doesn't matter how many virtual functions you have for the sizeof the class object. Considering this, I think you shouldn't worry too much about it.
Typically, every instance of a class with at least one virtual function will have an extra pointer stored with its explicit data members.
There's no way round this, but remember that (again typically) each virtual function table is shared between all instances of the class, so there is no great overhead to having multiple virtual functions or extra levels of inheritance once you've paid the "vptr tax" (small cost of vtable pointer).
For larger classes the overhead becomes much smaller as a percentage.
If you want functionality that does something like what virtual functions do, you are going to have to pay for it in some way. Actually using native virtual functions may well be the cheapest option.
The space cost of a vtable is one pointer (modulo alignment). The table itself is not placed into each instance of the class.
You have two options.
1) Don't worry about it.
2) Don't use virtual functions. However, not using virtual functions can just move the size into your code, as your code gets more complex.
Moving away from the non issue of the vtable pointer in your object:
Your code has other problems:
A * array = new A[1000];
array[0] = new B();
array[1] = new C();
The problem you are having is the slicing problem.
You can not put an object of class B into a space the size reserved for an object of class A.
You will just slice the B(or C) part of the object clean off leaving you with just the A part.
What you want to do. Is have an array of A pointers so that it hold each item by pointer.
A** array = new A*[1000];
array[0] = new B();
array[1] = new C();
Now you have another problem of destruction. Ok. This could go on for ages.
Short answer use boost:ptr_vector<>
boost:ptr_vector<A> array(1000);
array[0] = new B();
array[1] = new C();
Never allocte array like that unless you have to (Its too Java Like to be useful).
How many instances of A-derived classes do you expect?
How many distinct A-derived classes do you expect?
Note that even with a million of instances, we are talking about a total of 32MB. Up to 10 millions, don't sweat it.
Generally you need an extra pointer per instance, (if you are running on an 32 bit platform, the last 4 byte are due to alignment). Each class consumes additional (Number of virtual functions * sizeof(virtual function pointer) + fixed size) bytes for its VMT.
Note that, considering alignment for the doubles, even a single byte as type identifier will bring up the array element size to 32. So Stjepan Rajko's solution is helpful in some cases, but not in yours.
Also, don't forget the overhead of a general heap for so many small objects. You may have another 8 bytes per object. With a custom heap manager - such as an object/size specific pool allocator - you can save more here and employ a standard solution.
If you're going to have millions of these things, and memory is a serious concern for you, then you probably ought not to make them objects. Just declare them as a struct or an array of 3 doubles (or whatever), and put the functions to manipulate the data somewhere else.
If you really need the polymorphic behavior, you probably can't win, since the type information you'd have to store in your struct will end up taking up a similar amount of space...
Is it likely that you'll have large groups of objects all of the same type? In that case, you could put the type information one level "up" from the individual "A" classes...
Something like:
class A_collection
{
public:
virtual void update() = 0;
}
class B_collection : public A_collection
{
public:
void update() { /* stuff goes in here... */ }
private:
vector<double[3]> points;
}
class C_collection { /* Same kind of thing as B_collection, but with different update function/data members */
As others already said, in a typical popular implementation approach, once a class becomes polymorphic, each instance grows by a size of an ordinary data pointer. It doesn't matter how many virtual functions you have in your class. On a 64-bit platform the size would increase by 8 bytes. If you observed 8-byte growth on a 32-bit platform, it could have been caused by padding added to 4-byte pointer for alignment (if your class has 8-byte alignment requirement).
Additionally, it is probably worth noting that virtual inheritance can inject extra data pointers into class instances (virtual base pointers). I'm only familiar with a few implementations and in at least one the number of virtual base pointers was the same as the number of virtual bases in the class, meaning that virtual inheritance can potentially add multiple internal data pointers to each instance.
If you know all of the derived types and their respective update functions in advance, you could store the derived type in A, and implement manual dispatch for the update method.
However, as others are pointing out, you are really not paying that much for the vtable, and the tradeoff is code complexity (and depending on alignment, you might not be saving any memory at all!). Also, if any of your data members have a destructor, then you also have to worry about manually dispatching the destructor.
If you still want to go this route, it might look like this:
class A;
void dispatch_update(A &);
class A
{
public:
A(char derived_type)
: m_derived_type(derived_type)
{}
void update()
{
dispatch_update(*this);
}
friend void dispatch_update(A &);
private:
char m_derived_type;
};
class B : public A
{
public:
B()
: A('B')
{}
void update() { /* stuff goes in here... */ }
private:
double a, b, c;
};
void dispatch_update(A &a)
{
switch (a.m_derived_type)
{
case 'B':
static_cast<B &> (a).update();
break;
// ...
}
}
You're adding a single pointer to a vtable to each object - if you add several new virtual functions the size of each object will not increase. Note that even if you're on a 32-bit platform where pointers are 4 bytes, you're seeing the size of the object increase by 8 probably due to the overall alignment requirements of the structure (ie., you're getting 4 bytes of padding).
So even if you made the class non-virtual, adding a single char member would likely add a full 8 bytes to the size of each object.
I think that the only ways you'll be able to reduce the size of you objects would be to:
make them non-virtual (you you really need polymorphic behavior?)
use floats instead of double for one or more data members if you don't need the precision
if you're likely to see many objects with the same values for the data members, you might be able to save on memory space in exchange for some complexity in managing the objects by using the Flyweight design pattern
Not an answer to the question directly, but also consider that the declaration order of your data members can increase or decrease your real memory consumption per class object. This is because most compilers can't (read: don't) optimize the order in which class members are laid out in memory to decrease internal fragmentation due to alignment woes.
Given all the answers that are already here, I think I must be crazy, but this seems right to me so I'm posting it anyways. When I first saw your code example, I thought you were slicing the instances of B and C, but then I looked a little closer. I'm now reasonably sure your example won't compile at all, but I don't have a compiler on this box to test.
A * array = new A[1000];
array[0] = new B();
array[1] = new C();
To me, this looks like the first line allocates an array of 1000 A. The subsequent two lines operate on the first and second elements of that array, respectively, which are instances of A, not pointers to A. Thus you cannot assign a pointer to A to those elements (and new B() returns such a pointer). The types are not the same, thus it should fail at compile time (unless A has an assignment operator that takes an A*, in which case it will do whatever you told it to do).
So, am I entirely off base? I look forward to finding out what I missed.
If you really want to save memory of virtual table pointer in each object then you can implement code in C-style...
E.g.
struct Point2D {
int x,y;
};
struct Point3D {
int x,y,z;
};
void Draw2D(void *pThis)
{
Point2D *p = (Point2D *) pThis;
//do something
}
void Draw3D(void *pThis)
{
Point3D *p = (Point3D *) pThis;
//do something
}
int main()
{
typedef void (*pDrawFunct[2])(void *);
pDrawFunct p;
Point2D pt2D;
Point3D pt3D;
p[0] = &Draw2D;
p[1] = &Draw3D;
p[0](&pt2D); //it will call Draw2D function
p[1](&pt3D); //it will call Draw3D function
return 0;
}

C++ question about setting class variables

I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers. Given the following code:
#include <iostream>
#include <map>
using namespace std;
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar*>& b) {
bars = b;
}
void hello() {
cout << bars[0]->id << endl;
}
protected:
map<int,Bar*> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar*> testbars;
testbars[0] = new Foo::Bar;
testbars[0]->id = 10;
foo.set_bars(testbars);
foo.hello();
return(0);
}
I get the expected output of 5 & 10. However, my lack of understanding about references and pointers and such in C++ make me wonder if this will actually work in the wild, or if once testbars goes out of scope it will barf. Of course, here, testbars will not go out of scope before the program ends, but what if it were created in another class function as a function variable? Anyway, I guess my main question is would it better/safer for me to create the bars class variable as a pointer to the map map?
Anyway, I guess my main question is
would it better/safer for me to create
the bars class variable as a pointer
to the map map?
No. C++ is nothing like Java in this and may other respects. If you find yourself using pointers and allocating new'd objects to them a lot, you are probably doing something wrong. To learn the right way to do things, I suggest getting hold of a copy of Accelerated C++ by Koenig & Moo,
The member variable bars is a separate instance of a "dictionary"-like/associative array class. So when it is assigned to in set_bars, the contents of the parameter b are copied into bars. So there is no need to worry about the relative lifetimes of foo and testbars, as they are independent "value-like" entites.
You have more of a problem with the lifetimes of the Bar objects, which are currently never going to be deleted. If you add code somewhere to delete them, then you will introduce a further problem because you are copying the addresses of Bar objects (rather than the objects themselves), so you have the same object pointed to by two different maps. Once the object is deleted, the other map will continue to refer to it. This is the kind of thing that you should avoid like the plague in C++! Naked pointers to objects allocated with new are a disaster waiting to happen.
References (declared with &) are not different from pointers with regard to object lifetimes. To allow you to refer to the same object from two places, you can use either pointers or references, but this will still leave you with the problem of deallocation.
You can get some way toward solving the deallocation problem by using a class like shared_ptr, which should be included with any up-to-date C++ environment (in std::tr1). But then you may hit problems with cyclical pointer networks (A points to B and B points to A, for example), which will not be automatically cleaned up.
For every new you need a corresponding delete.
If you try and reference the memory after you call delete - where ever that is - then the program will indeed "barf".
If you don't then you will be fine, it's that simple.
You should design your classes so that ownership of memory is explicit, and that you KNOW that for every allocation you are doing an equal deallocation.
Never assume another class/container will delete memory you allocated.
Hope this helps.
In the code below you can pass map of Bars and then will be able to modify Bars outside of the class.
But. But unless you call set_bars again.
It is better when one object is responsible for creation and deletion of Bars. Which is not true in your case.
If you want you can use boost::shared_ptr< Bars > instead of Bars*. That will be more Java like behavior.
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { freeBarsMemory(); }
struct Bar {
int id;
};
typedef std::map<int,Bar*> BarsList;
void set_bars(const BarsList& b) {
freeBarsMemory();
bars = b;
}
void hello() {
std::cout << bars[0]->id << std::endl;
}
protected:
BarsList bars;
void freeBarsMemory()
{
BarsList::const_iterator it = bars.begin();
BarsList::const_iterator end = bars.end();
for (; it != end; ++it)
delete it->second;
bars.clear();
}
};
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers.
The confusion appears to come from a combination of data that is on the heap and data that is not necessarily on the heap. This is a common cause of confusion.
In the code you posted, bars is not a pointer. Since it's in class scope, it will exist until the object containing it (testbars) is destroyed. In this case testbars was created on the stack so it will be destroyed when it falls out of scope, regardless of how deeply nested that scope is. And when testbars is destroyed, subobjects of testbars (whether they are parent classes or objects contained within the testbars object) will have their destructors run at that exact moment in a well-defined order.
This is an extremely powerful aspect of C++. Imagine a class with a 10-line constructor that opens a network connection, allocates memory on the heap, and writes data to a file. Imagine that the class's destructor undoes all of that (closes the network connection, deallocates the memory on the heap, closes the file, etc.). Now imagine that creating an object of this class fails halfway through the constructor (say, the network connection is down). How can the program know which lines of the destructor will undo the parts of the constructor that succeeded? There is no general way to know this, so the destructor of that object is not run.
Now imagine a class that contains ten objects, and the constructor for each of those objects does one thing that must be rolled back (opens a network connection, allocates memory on the heap, writes data to a file, etc.) and the destructor for each of those objects includes the code necessary to roll back the action (closes the network connection, deallocates objects, closes the file, etc.). If only five objects are successfully created then only those five need to be destroyed, and their destructors will run at that exact moment in time.
If testbars had been created on the heap (via new) then it would only be destroyed when calling delete. In general it's much easier to use objects on the stack unless there is some reason for the object to outlast the scope it was created in.
Which brings me to Foo::bar. Foo::bars is a map that refers to objects on the heap. Well, it refers to pointers that, in this code example, refer to objects allocated on the heap (pointers can also refer to objects allocated on the stack). In the example you posted the objects these pointers refer to are never deleted, and because these objects are on the heap you're getting a (small) memory leak (which the operating system cleans up on program exit). According to the STL, std::maps like Foo::bar do not delete pointers they refer to when they are destroyed. Boost has a few solutions to this problem. In your case it's probably be easiest to simply not allocate these objects on the heap:
#include <iostream>
#include <map>
using std::map;
using std::cout;
class Foo {
public:
Foo() {
// normally you wouldn't use the parenthesis on the next line
// but we're creating an object without a name, so we need them
bars[0] = Bar();
bars[0].id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar>& b) {
bars = b;
}
void hello() {
cout << bars[0].id << endl;
}
protected:
map<int,Bar> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar> testbars;
// create another nameless object
testbars[0] = Foo::Bar();
testbars[0].id = 10;
foo.set_bars(testbars);
foo.hello();
return 0;
}