This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++'s “placement new”
I just learned about the placement new operator and tried creating my own memory manager.
Here is the code of my template base class for Memory
#ifndef _MEMORY_BASE_H_
#define _MEMORY_BASE_H_
//=========================================!
#include <new>
#include <exception>
#include <iostream>
//=========================================!
using namespace std;
//=========================================!
template <typename T>
class Memory_Base
{
public :
//standard new
void* operator new(size_t T);
// placement new
void* operator new(size_t T,void* pAddress);
//standard delete
void operator delete(void* pAny);
};
//=========================================!
// Implementation
//=========================================!
template <typename T>
void* Memory_Base<T>::operator new(size_t T)
{
cout << "Memory_Base<T>:: new called" << endl;
void* pTemp = malloc(sizeof(T));
if(!pTemp)
throw bad_alloc();
else
return pTemp;
}
//=========================================!
template <typename T>
void* Memory_Base<T>::operator new(size_t T,void* pAddress)
{
cout << "Memory_Base<T>:: placement new called" << endl;
return pAddress;
}
//=========================================!
template <typename T>
void Memory_Base<T>::operator delete(void* pAny)
{
cout << "Memory_Base<T>:: delete called" << endl;
free(pAny);
}
//=========================================!
#endif
Now, i inherited myclass from above class,in another header file , something like as below
#ifndef _MY_CLASS_H_
#define _MY_CLASS_H_
//=========================!
#include "Memory_Base.h"
//=========================!
class MyClass :public Memory_Base<MyClass>
{
private :
int ma;
public :
MyClass():ma(-1){}
~MyClass(){}
};
//============================!
#endif
Now, in my main, i am trying to create objects of myclass in the following manner
//============================!
#include "MyClass.h"
//============================!
int main()
{
// This is how new for MyClass is called
MyClass* pMyClass = new MyClass();
// This is how placement new for MyClass is called
MyClass obj[10];
MyClass* pMyClass1 = new(&obj)MyClass();
return 0;
}
//============================!
Questions ::
1. When i run main, the base address of obj and pMyClass1 were the same, as expected. However, i am just returning the pointer pAddress, then how the placement new works ?
my obj[10], is in stack, but, the destructor is not getting called.
Any ideas ?
Atul
P.S :: I have to implement the new[] and delete[] in Memory_Base.
MyClass obj[10];
Allocates and creates 10 objects of the type MyClass on the local storage.
Further,
MyClass* pMyClass1 = new(&obj)MyClass();
Just calls the constructor MyClass::MyClass(). The this pointer in the MyClass constructor will be equal to &obj. The returned pointer pMyClass1 will therefore be equal to &obj.
Also, In case of placement new it is your responsibility to destroy the placed object by explicitly calling the destructor, the placed objects destructor wont be called implcitly.
Since, the array of objects since placed on stack will be deallocated once the program returns in your case.
Related
I need to provide a utility function where both memory allocation and object construction take place and the user gets the pointer in return. Similarly, there is a need to provide a utility function for deallocation and destruction also.
Here is what I implemented: (I have not implemented for array type though)
#include <cstdlib> // for malloc
#include <iostream> // for cout
#include <string> // for memset
// C++ class with some initial state x = 10
class SomeClass {
public:
SomeClass() : x(10) {}
int x = 0;
};
template<typename T, typename ... Args>
inline T* MY_MODULE_NEW(Args&&... args) {
// some custom allocator logic here which allocates just raw memory
// for example purpose just use malloc
void *p = malloc(sizeof(T));
memset(p,0,sizeof(T));
T* t = new(p) T(std::forward<Args>(args)...);
return t;
}
template<typename T>
inline void MY_MODULE_DELETE(T* ptr) {
ptr->~T();
// some custom allocator logic here, which deallocates raw memory
// for example purpose just use free
free(ptr);
}
int main() {
SomeClass* sc = MY_MODULE_NEW<SomeClass>();
std::cout << sc->x << std::endl;
SomeClass* sc2 = MY_MODULE_NEW<SomeClass>(*sc);
std::cout << sc2->x << std::endl;
MY_MODULE_DELETE(sc);
MY_MODULE_DELETE(sc2);
}
I have the following concerns:
From the performance point of view, Is this inline function good enough? Can we do better?
Personally I feel MY_MODULE_NEW<SomeClass>(...) syntax is almost similar to the canonical syntax for operator new which is new SomeClass(). Is there any other idiomatic way to achieve the same result?
Thank You!
I am trying to understand overloading new operator. I wrote the code as below.
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class loc
{
int lo, la;
public:
loc()
{
}
loc(int x, int y)
{
cout << "In constructor\n";
lo = x;
la = y;
}
void show()
{
cout << lo << " ";
cout << la << endl;
}
void *operator new(size_t sz);
void operator delete(void *p);
};
void *loc::operator new(size_t sz)
{
cout << "in Overloaded new\n";
void *p = malloc(sz);
return p;
}
void loc::operator delete(void *p)
{
cout << "in Overloaded delete\n";
free(p);
}
int main()
{
loc *p1 = new loc(10, 20);
p1->show();
delete p1;
return 0;
}
I thought it won't call the constructor because I overloaded the new operator with malloc function call inside overloading function. But the output is as below.
in Overloaded new
In constructor
10 20
in Overloaded delete
That means constructor is getting called. How this is possible? Does this mean will malloc() call constructor?
A new expression results in two separate things happening: allocation of the memory needed by the object begin created, and initialization of the object.
The new operator, on the other hand, just handles the allocation part. When you overload the new operator with respect to a specific class, you are replacing the allocation of memory to the object.
This division of functions makes sense when you realize that not all objects are allocated on the heap. Consider the following case:
int main() {
string someString;
..
}
The local variable is not dynamically allocated; new is not used; however the object still needs to be initialized so the constructor is still called. Note that you did not need to explicitly call the constructor - it is implicit in the language that an appropriate constructor will always be called to initialize an object when it is created.
When you write a 'new expression', the compiler knows to emit instructions to invoke the new operator (to allocate memory as needed) and then to call the constructor (to initialize the object). This happens whether or not you overload the new operator.
#include <new>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
struct foo {};
inline void* operator new(size_t size, foo*) throw (std::bad_alloc)
{
std::cout << "my new " << size << std::endl;
return malloc(size);
}
inline void operator delete(void* p, foo*) throw()
{
std::cout << "my delete" << std::endl;
free(p);
}
int main()
{
delete new((foo*)NULL) foo;
}
Output (via ideone):
my new 1
My thinking was that C++ would free an object new'd with additional arguments with its matching delete of the same arguments, but I was obviously incorrect.
What is the correct way to get the code above to call my overloaded delete?
When you use any form of placement new, except for the std::nothrow_t versions, you need to explicitly destroy the object and release its memory with whatever means you see fit. The overloaded version of operator delete() is still required to exist, however, because it is used if construction of the object throws an exception! In this case, no pointer is returned because an exception is thrown. Getting rid of the memory has, thus, to be done in this process of allocation.
That is, you main() should look something like this:
int main()
{
foo* p = new (static_cast<foo*>(0)) foo;
p->~foo();
operator delete(p, static_cast<foo*>(0));
}
This is a follow up to my previous question,
Initializing a class using malloc
Accepted answer on the question works and gives me new/delete on the avr-gcc, here is the problem but my overloaded new delete wracks havoc on regular gcc, what is the proper way to overload new delete all my classes derive from a common base class so ideally i would like to just override new delete for my object so it does not mess with stl stdlib etc.
'new' and 'delete' can overloaded inside the common Object base class. So, that will be applicable only to that hierarchy.
class Object {
public:
void* operator new (size_t size);
void operator delete (void *p);
};
class Derived : public Object {
// uses the above versions of new/delete
};
[Note: It's an added advantage for you as all your class are getting derived from a common Object class (as mentioned in your question and the link)]
Overload the new & delete inside your own class & not Globally.
For eg: If name of your common class is YourClass, You can overload them as follows:
void *YourClass::operator new(size_t size)
{
void *p;
cout << "In overloaded new.";
p = malloc(size);
if(!p)
{
throw std::bad_alloc; //Throw directly than with named temp variable
}
return p;
}
void YourClass::operator delete(void *p)
{
cout << "In overloaded delete.\n";
free(p);
}
void *YourClass::operator new[](size_t size)
{
void *p;
cout << "Using overload new[].\n";
p = malloc(size);
if(!p)
{
throw std::bad_alloc;
}
return p;
}
void YourClass::operator delete[](void *p)
{
cout << "Free array using overloaded delete[]\n";
free(p);
}
All classes derived from YourClass will be able to use these overloaded new and delete operators.
We want to work on low latency system, heap allocation is costlier in the application. but for some extent object creation on heap is allowed. Thats why we want indication whether object is created is on heap or not..?
Is the below methodology is the correct way to find out object created on heap memory..?
Will have generic class where new and delete operator is overloaded to maintain heap allocated pointers....
#include <iostream>
#include <set>
using namespace std;
class MemStat //base class
{
typedef set<MemStat*> POINTERS;
static POINTERS m_ptrlist;
public:
void* operator new (size_t size)
{
MemStat* ptr = ::new MemStat;
m_ptrlist.insert(ptr);
return ptr;
}
void operator delete(void* dptr)
{
MemStat* ptr = static_cast<MemStat*>(dptr);
m_ptrlist.erase(ptr);
::delete ptr;
}
// void* operator new[] (size_t sz);
// void operator delete[] (void*);
bool is_on_heap() { m_ptrlist.find(this) != m_ptrlist.end(); }
protected: // ctor & dtor are protected for restrictions
MemStat() { }
virtual ~MemStat() { }
MemStat(const MemStat&) { }
const MemStat& operator=(const MemStat& ) { return *this; }
};
MemStat::POINTERS MemStat::m_ptrlist;
for the end user classes which we need to check for the heap creation will be derived from MemStat class uses new & delete operator call while instantiating base class object.
class MyClass : public MemStat //end user class
{
};
int main()
{
MyClass* myptr = new MyClass;
MyClass obj;
cout << myptr->is_on_heap() << endl; //results into yes
cout << obj.is_on_heap() << endl; //reults into no
delete myptr;
}
Note that your scheme fails miserably as soon as a MyClass object is a sub-object (inherited or contained) of another object which might or might not by allocated dynamically. (And the tricks I know for preventing dynamic allocation fail on that one as well.)
So what you're doing just further slows down heap allocation without gaining much. Except for a few very rare circumstances, where an object is allocated is something your class' users decide.
If they think they need to dynamically allocate one, who are you to disagree?