It is not easy to predict the complexity of the function.
If user expand code for compiler, it will take less time to compile the code.
1. Object Construction and Destruction
Destructor will be inserted before all leaving-point in a function/section.
Given destructor will not be inserted before the object is created, create the object near the place it is used as possible as you can.
global objects - sstored in data segment
local static objects - constructor and destructor will be called only once
const Matrix& identity()
{
static Matrix mat_identity;
return mat_identity;
}
2. Operator new and delete
// for new operator
int *p = new int(5);
// actually 2 steps are done
int *pi;
if (pi = __new(sizeof(int));
*pi = 5;
// for delete operator
delete pi;
// actually doing
if (pi != 0)
__delete(pi);
// for arrays
int *p_array = new int[5];
// which actually means
int *p_array = (int*) __new(5*sizeof(int));
delete[] p_array;
// if using
delete p_array;
// only the first element will be destructed, and other elements still exist, although memory is retrieved
// if there is a default constructor defined, vec_new() will be invoked
Point3d *p_array = new Point3d[10];
// it will be converted into
Point3d *p_array;
p_array = vec_new(0, sizeof(Point3d), 10, &Point3d::Point3d, &Point3d::~Point3d);
- operator new uses standard malloc()
- operator delete uses standard free()
After delete:
- the object point p points to is over
- point p still can be used as a pointer (may cause some unexpected bugs sometimes)
// totally NOT a good idea to do so
Point *ptr = new Point3d[10];
// ONLY Point::~Point is invoked here...
delete[] ptr;
The destructor applied here is the Point::~Point() which is passed into vec_delete(), and also the size of each element (size of Point, not Point3d). So you have to
for (int ix = 0; ix < elem_count; ++ix)
{
Point3d *p = &((Point3d*)ptr)[ix];
delete p;
}
placement Operator new - an overloaded new operator, which needs the second argument void*
Point2w *ptw = new(arena) Point2w;
arena points to a block in memory to place new created Point2w object
void* operator new(size_t, void* p)
{
return p;
}
the whole procedure could be converted into
Point2w *ptw = (Point2w*) arena;
if ( ptw != 0)
ptw->Point2w::Point2w();
// incorrect way
Point2w *p2w = new (arena) Point2w;
delete p2w; // delete will also free the memory p2w points to
p2w = new (arena) Point2w;
// correct way
p2w->~Point2w;
p2w = new (arena) Point2w;
3. Temporary Objects
T operator + (const T&, const T&);
T a, b;
T c = a + b;
// 1. copy constructor is used to send a+b to c, then no temporary object is needed
// 2. NRV may work depending on the definition of the operator+()
c = a + b;
// for assignment operator, temporary object cannot be ignored
// it will be converted to
T temp;
temp.operator+(a, b); // NRV works here
c.operator=(temp);
temp.T::~T();
- It should be the last step of a full-expression to destroy the temporary object.
- Those temporary object hold result of expression will be kept until the object initialization is over.
- If a temporary object is binding with a reference, it will be kept unit the end of the scope of the temporary object or the end of the reference.
For compilers:
- temporary objects induce the efficiency lose compared to Fortran
- reading and writing from stack/heap may lose efficiency, compiler will try to put some member of temporary object into register.