Say you have a simple class with some storage data structure (list, vector, queue, etc)
class MyClass
{
public:
std::list<OtherClass*> m_myList;
};
Now let's say we allocate this class on the heap.
MyClass* pClass = new MyClass();
Now when we add more items to this list, are they on the heap or on the stack?
Example:
OtherClass* pOtherClass = new OtherClass();
pClass->m_myList.push_front(pOtherClass);
Thanks for the help!
The standard collection classes use an Allocator class to allocate memory for the items being stored. The default allocator will allocate the data on the free store. You can provide your own if you want to, and I suppose if you wanted to badly enough you could have it allocate space on the stack, but you'd have to do a fair amount of extra work to make that happen.
Note that you do not have to allocate the object itself on the free store to make that happen either. In fact, your MyClass *pClass = new MyClass(); is usually a poor idea. You normally just want to use MyClass Class; and be done with it. That will allocate space for the collection object itself (normally quite small) on the stack, but space for what it stores will still normally come from the free store (again, via the allocator). Among other things, this helps automate memory management -- when the collection object goes out of scope, it'll be destroyed. Its destructor will the destroy the objects it contains and release the memory (all automatically).
std::list stores to elements on the heap so it doesn't matter where your class is.
The default allocator for the standard template classes allocate on the heap, no matter what.
So, they would be on the heap.
The simple rule: If you're allocating new OtherClass objects with new, then they are on the heap. new only allocates memory from the heap. (Exception: If you use a custom allocator, which is an advanced C++ feature, they can be in whatever memory area of your choosing.)
Your m_myList is an instance of std::list, which happens to also store its internal information on the heap (but that is an implementation detail and you usually don't need to worry about it).
Related
I just learned about the C++ construct called "placement new". It allows you to exactly control where a pointer points to in memory. It looks like this:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)];
void* place = memory;
Fred* f = new(place) Fred(); // Create a pointer to a Fred(),
// stored at "place"
// The pointers f and place will be equal
...
}
(example from C++ FAQ Lite)
In this example, the this pointer of Fred will be equal to place.
I've seen it used in our team's code once or twice. In your experience, what does this construct enable? Do other pointer languages have similar constructs? To me, it seems reminiscent of equivalence in FORTRAN, which allows disparate variables to occupy the same location in memory.
It allows you to do your own memory management. Usually this will get you at best marginally improved performance, but sometimes it's a big win. For example, if your program is using a large number of standard-sized objects, you might well want to make a pool with one large memory allocation.
This sort of thing was also done in C, but since there are no constructors in C it didn't require any language support.
It is also used for embedded programming, where IO devices are often mapped to specific memory addresses
Its usefull when building your own container like objects.
For example if you were to create a vector. If you reserve space for a large number of objects you want to allocate the memory with some method that does not invoke the constructor of the object (like new char[sizeof(object) * reserveSize]). Then when people start adding objects into the vector you use placement new to copy them into allocated memory.
template<typename T>
class SillyVectorExample
{
public:
SillyVectorExample()
:reserved(10)
,size(0)
,data(new char[sizeof(T) * reserved])
{}
void push_back(T const& object)
{
if (size >= reserved)
{
// Do Somthing.
}
// Place a copy of the object into the data store.
new (data+(sizeof(T)*size)) T(object);
++size;
}
// Add other methods to make sure data is copied and dealllocated correctly.
private:
size_t reserved;
size_t size;
char* data;
};
PS. I am not advocating doing this. This is just a simplified example of how containers can work.
I've used it when constructing objects in a shared memory segment.
Placement new can be used to create type-safe unions, such as Boost's variant.
The union class contains a buffer as big as the biggest type it's specified to contain (and with sufficient alignment). It placement news objects into the buffer as required.
I use this construct when doing C++ in kernel mode.
I use the kernel mode memory allocator and construct the object on the allocated chunk.
All of this is wrapped in classes and functions, but in the end I do a placement new.
Placement new is NOT about making pointers equal (you can just use assignment for that!).
Placement new is for constructing an object at a particular location. There are three ways of constructing an object in C++, and placement new is the only one that gives you explicit control over where that object "lives". This is useful for several things, including shared memory, low-level device I/O, and memory pool/allocator implementation.
With stack allocation, the object is constructed at the top of the stack, wherever that happens to be currently.
With "regular" new, the object is constructed at an effectively arbitrary address on the heap, as managed by the standard library (unless you've overridden operator new).
Placement new says "build me an object at this address specifically", and its implementation is simply an overload of operator new that returns the pointer passed to it, as a means of getting to the remainder of the machinery of the new operator, which constructs an object in the memory returned by the operator new function.
It's also worth noting that the operator new function can be overloaded with arbitrary arguments (just as any other function). These other arguments are passed via the "new(arg 2, arg3, ..., argN)" syntax. Arg1 is always implicitly passed as "sizeof(whatever you're constructing)".
By controlling the exact placement, you can align things in memory and this can sometimes be used to improve CPU fetch/cache performance.
Never actually saw it in use, though
It can be useful when paging out memory to a file on the hard drive, which one might do when manipulating large objects.
Placement new allows the developer to allocate the memory from preallocated memory chunk. If the system is larger, then developers go for using placement new. Now I am working on a larger avionics software there we allocate the large memory that is required for the execution of application at the start. And we use the placement new to allocate the memory wherever required. It increases the performance to some amount.
seems to me like a way of allocating an object on the stack ..
I've used it to create objects based on memory containing messages received from the network.
Suppose I am creating an object of STL map in C++ i.e map<string,char>mymap``$. Now, I want to know how memory is being allocated to this object? My point of confusion is that there is no dynamic allocation and we don't know the size of the container in prior. So, from where and how memory is allocated to the object mymap?
there is no dynamic allocation
Sure there is, but it's under the hood. std::map is usually stored as a tree, so a new node is allocated whenever a new object is inserted into it. Dynamically. Just because you don't explicitly write new, it doesn't mean it doesn't happen under the hood.
On the destructor of std::map, the nodes are automatically deleted. Note however that if the nodes contain dynamically allocated objects, those will not be deleted by the map.
So, from where and how memory is allocated to the object mymap?
The default allocator for all Standard containters is std::allocator, from where your container gets memory and releases to when it is done with the memory. You can use custom allocator, and then keep track of all the allocations and deallocations if you want to.
I am writing a memory manager in c++. The aim is to allocate a set amount of memory at the start using malloc and then overload new and delete so that it uses that memory. I almost have it working my only problem is how i am keeping track of what is where in the memory.
I created a vector of structs which holds information such as size, location and if it is free or not.
The problem is when i call push_back it attempts to use my overloaded new function. This is where it fails because it can't use my overloaded new until it has pushed back the first structure of information.
Does anyone know how i can resolve this or a better way to keep track of the memory?
Don't overload global operator new!
The easiest and (WARNING; subjective ->) best solution would be to define your own Allocator which you'll use when dealing with allocation on the free-store (aka. heap). All STL containers have support for passing an AllocatorType as a template argument.
Overloading global operator new/operator delete might seem like a neat solution, but I can almost guarantee you that it will cause you troubles as the developing goes by.
Inside this custom made allocator you can keep track of what goes where, but make the internal std::vector (or whatever you'd like to use, a std::map seems more fitting to me) will use the default operator new/operator delete.
How do I create my own allocator?
The link below will lead you to a nice document with information regarding this matter:
stdcxx.apache.org - Building Your Own Allocators (heavily recommended)
Using a custom allocator when required/wanted will make you not run into any chicken and egg problem when trying to allocate memory for the allocator that will allocate memory, but the allocator must have allocated memory to use the allocator methods.. and what will allocate memory for the allocator but the allocator? Well we will need to allocate memory for that allocator and that allocator must have it's own allocator, though that allocator need memory, provided by another allocator?
Maybe I should just get myself a dog instead, they don't lay eggs - right?
create a class and overload new only in this class. you will not have problems with your vector. you will be able to use your own new with ::new A and the normal new with new A
class C
{
public:
void* operator new( size_t n ) ;
// ...
} ;
otherwise, you can use your own operator function rather than overload operator new :
a basic idea of an allocator :
int *i = myGetMem(i); // and myGetMem() allocates sizeof(*i) bytes of memory.
so you will not have problems with using the vector.
in fact, a real memory allocator keeps the information you put on the vector in the memory allocated it self :
you can take an algorithm for getmem/freemem to adapt it to your case. it can be helpfull.
e.g. : i want to allocate 10 bytes, the memory at #1024 contain information about memory allocated and the allocator returns an adress after 1024, maybe #1030 (depending of the information stored) as the start of allocated memory. so the user gets adress 1030 and he has memory between 1030 and 103A.
when calling the deallocator, the information at the beginning is used to correctly free the memory and to put it back in the list of avaible memory.
(the list of availvle memory is stored in popular alorithms in an array of linked lists of free memories organized by size with algorithms to avoid and minimize fragmentation)
this can resolve your need to the vector.
You can create a vector using any custom allocator.
It is declared in the following manner:
std::vector<YourStruct, YourOwnAllocator> memory_allocations;
YourOwnAllocator is going to be a class which will allocate the data needed for the vector bypassing your overloaded operators.
In needs to provide all the methods and typedefs listed here.
If I use std::vector<> or std::string, do I need to allocate them in heap as well. For example:
int main() {
std::vector<int>* p = new std::vector<int>();
delete p;
}
In Java and C#, objects are always allocated in heap using this syntax. I wonder is it efficient to do the same thing in C++? Because whenever I create a class in C++, I usally mix between stack and heap variables. Let's say:
class simple {
int a;
double b;
std::string c;
std::vector<int> d;
....
};
I wonder what's the best practice should I follow when using object in C++?
All data should be allocated on heap?
All data could be mixed?
or...
Thanks,
Chan
I try to allocate the objects on stack whenever possible as I don't have to worry about releasing the memory in such case. Only when I explictly want to control the life time of an object I will allocate the object on the heap. Even if the object internally allocates memory on heap, you can still create the object itself on the stack. There is no restriction on that.
You should avoid creating objects with large size on stack, because casual stack overflow on stress (large input data) is rarely revealed by testing and so will make your end users unhappy that your software crashes.
About string and vector and other STL containers you should not worry, because they use dynamic allocation internally. So the answer is NO, it is safe to construct them into stack and it is usually overkill to allocate them dynamically.
What might be dangerous are static-sized arrays, things that enwrap such arrays like boost::array or classes that have such as data members. Experts often use pimpl idiom to make their classes internally dynamic.
Stack is extremely quick, but use its quickness only where it really benefits the performance. It is safer to be careful with it. Avoid taking dangerous idioms like "I allocate everything on stack".
No; in general, use the stack unless the variable's lifetime exceeds that of the function.
The container classes will allocate their own memory from the heap; the only data on the stack is whatever bookkeeping the container class needs such as a pointer to the head, size, etc.
Additionally I would recommend avoiding manual new/delete and utilizing shared_ptr etc techniques.
I just learned about the C++ construct called "placement new". It allows you to exactly control where a pointer points to in memory. It looks like this:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)];
void* place = memory;
Fred* f = new(place) Fred(); // Create a pointer to a Fred(),
// stored at "place"
// The pointers f and place will be equal
...
}
(example from C++ FAQ Lite)
In this example, the this pointer of Fred will be equal to place.
I've seen it used in our team's code once or twice. In your experience, what does this construct enable? Do other pointer languages have similar constructs? To me, it seems reminiscent of equivalence in FORTRAN, which allows disparate variables to occupy the same location in memory.
It allows you to do your own memory management. Usually this will get you at best marginally improved performance, but sometimes it's a big win. For example, if your program is using a large number of standard-sized objects, you might well want to make a pool with one large memory allocation.
This sort of thing was also done in C, but since there are no constructors in C it didn't require any language support.
It is also used for embedded programming, where IO devices are often mapped to specific memory addresses
Its usefull when building your own container like objects.
For example if you were to create a vector. If you reserve space for a large number of objects you want to allocate the memory with some method that does not invoke the constructor of the object (like new char[sizeof(object) * reserveSize]). Then when people start adding objects into the vector you use placement new to copy them into allocated memory.
template<typename T>
class SillyVectorExample
{
public:
SillyVectorExample()
:reserved(10)
,size(0)
,data(new char[sizeof(T) * reserved])
{}
void push_back(T const& object)
{
if (size >= reserved)
{
// Do Somthing.
}
// Place a copy of the object into the data store.
new (data+(sizeof(T)*size)) T(object);
++size;
}
// Add other methods to make sure data is copied and dealllocated correctly.
private:
size_t reserved;
size_t size;
char* data;
};
PS. I am not advocating doing this. This is just a simplified example of how containers can work.
I've used it when constructing objects in a shared memory segment.
Placement new can be used to create type-safe unions, such as Boost's variant.
The union class contains a buffer as big as the biggest type it's specified to contain (and with sufficient alignment). It placement news objects into the buffer as required.
I use this construct when doing C++ in kernel mode.
I use the kernel mode memory allocator and construct the object on the allocated chunk.
All of this is wrapped in classes and functions, but in the end I do a placement new.
Placement new is NOT about making pointers equal (you can just use assignment for that!).
Placement new is for constructing an object at a particular location. There are three ways of constructing an object in C++, and placement new is the only one that gives you explicit control over where that object "lives". This is useful for several things, including shared memory, low-level device I/O, and memory pool/allocator implementation.
With stack allocation, the object is constructed at the top of the stack, wherever that happens to be currently.
With "regular" new, the object is constructed at an effectively arbitrary address on the heap, as managed by the standard library (unless you've overridden operator new).
Placement new says "build me an object at this address specifically", and its implementation is simply an overload of operator new that returns the pointer passed to it, as a means of getting to the remainder of the machinery of the new operator, which constructs an object in the memory returned by the operator new function.
It's also worth noting that the operator new function can be overloaded with arbitrary arguments (just as any other function). These other arguments are passed via the "new(arg 2, arg3, ..., argN)" syntax. Arg1 is always implicitly passed as "sizeof(whatever you're constructing)".
By controlling the exact placement, you can align things in memory and this can sometimes be used to improve CPU fetch/cache performance.
Never actually saw it in use, though
It can be useful when paging out memory to a file on the hard drive, which one might do when manipulating large objects.
Placement new allows the developer to allocate the memory from preallocated memory chunk. If the system is larger, then developers go for using placement new. Now I am working on a larger avionics software there we allocate the large memory that is required for the execution of application at the start. And we use the placement new to allocate the memory wherever required. It increases the performance to some amount.
seems to me like a way of allocating an object on the stack ..
I've used it to create objects based on memory containing messages received from the network.