I want to use malloc as it's memory assignment happens in O(1) rather than O(n) with the following code:
MyQuickInitArray(int size)
{
A = new T[size];
}
When A is of type:
T* A
I thought initializing an array of pointers will take O(1) because pointers are primitives but i doubled checked and the code above actually goes size times to the constructor of T. If this problem can be avoided by either malloc or something that i'm missing than it would be great.
As you correctly point out, new T[n] calls the constructors, whereas malloc() doesn't.
If you don't want to call the constructors (why?), then clearly new[] isn't right for you.
If, however, you do want to have the constructors called, then there is no way to get around the o(n) complexity.
If what you're looking for is an array of pointers to T, the correct syntax is as follows:
T** A = new T*[size];
This will not call T's constructor.
I thought initializing an array of pointers will take O(1)
You are not allocating an array of pointers, you are allocating an array of objects of type T with your code:
T *A = new T[size];
to allocate an array of pointers you need
typedef T *T_Ptr;
T_Ptr *A = new T_Ptr[size];
I'm using a typedef so that the syntax is cleaner.
If you have allocated space for your objects you can properly initialize them using C++'s "placement new" operator; in this case new is not allocating memory however it will call the constructor. http://www.cplusplus.com/forum/general/55150/ has an example, but generally you do not want to do this, you want to allocate your objects in a non-time-critical portion of your program instead.
What about overloading the new
void* class_name::operator new(size_t size)
{
cout<<"Allocating memory for object \n";
void *p;
p=malloc(size);
if(p==NULL)
cout<<"Memory allocation error\n\a";
else
return p;
}
For array
void* class_name::operator new[](size_t size)
{
cout<<"Allocating array of size "<<size<<endl;
void *p;
p=malloc (size);
if(p==NULL)
{
cout<<"Memory allocation error \n";
}
return p;
}
How it is used :
Class_name *objptr1,*objptr2;
objptr1=new class_name(10);
objptr2=new class_name[10];
Related
I am under the assumption that the code bellow is a unique_ptr to an array (aka not what I want)
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
arr[0] = *new int(1);
delete &arr[0]; // malloc error, want to avoid "delete"
However, I want an array that holds unique_ptrs like so...
std::unique_ptr<int> arr2 []; //Error, requires explicit size
arr2 = std::make_unique<int> [5]; //Desirable, does not compile
arr2[0] = std::make_unique<int>(1); //Desirable, does not compile
How do I go about making an array of unique_ptrs? If that is not possible, then how do I deal with a malloc error?
Do you want an array that holds unique_ptrs (as in the title), or a unique_ptr holding an array (as in your examples)?
If an array of unique_ptrs is what you want, then
std::vector<std::unique_ptr<int>>
or
std::array<std::unique_ptr<int>, 3>;
(for example) will do the job.
If a unique_ptr holding an array is what you're after, then unique_ptr<int[]> will work (there is a partial specialisation of unique_ptr to support it), although you can't use std::make_unique and will need to call operator new[] yourself:
std::unique_ptr<int[]> p{new int[42]};
However, if you think you need this, what you most likely really want is std::vector, and I'd strongly recommend using that instead.
Short answer: use vectors. They are much easier to work with and you don't have to explicidly allocate memory. You should also use typedefs for syntax simplicity.
typedef unique_ptr<int> intPtr;
vector<intPtr> vec;
vec.push_back(make_unique<int>(69));
auto myIntPtr = make_unique<int>(16);
vec.push_back(move(myIntPtr)); // unique ptrs cannot be copied, must be moved
unique_ptr<int[5]> p1; // valid syntax
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
At this point you have a unique_ptr to an array of int. This sounds like it is exactly what you want.
arr[0] = *new int(1);
But this is questionable. It dynamically allocates a single int, assigns 1 to the allocated int, then it assigns the value, 1, at the allocated int into the array at element 0. the allocated int is left hanging with nothing pointing at it, and is now exceptionally difficult to `delete. This is a memory leak.
delete &arr[0]; // malloc error, want to avoid "delete"
And as you've seen, this is fatal. Rather than attempting to delete the leaked int, delete has been invoked with a pointer to the array stored in the unique_ptr. Eventually the unique_ptrwill try todelete` the array and fail because it's already gone.
Based on comments, OP intends
std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0];
But I'd like to talk them out of this idea. Let's look at their end goal: a templated class
template <class TYPE>
class MyVector
{
std::unique_ptr<TYPE[]> arr; // array of whatever type
public:
MyVector(size_t size): arr(std::make_unique<TYPE[]> (size))
{
}
TYPE& operator[](size_t index)
{
return arr[index];
}
// note the complete lack of growing, shrinking and other vector goodness
// as they are not needed for this example.
};
We can use this class with just about anything.
int main()
{
// vector of int
MyVector<int> vec(5);
vec[0] = 1;
// vector of pointer to int (yuck)
MyVector<int*> vec2(5);
vec2[0] = new int(1);
delete vec2[0];
// vector of smart pointer to int (also yuck, but less yuck)
MyVector<std::unique_ptr<int>> vec3(5);
vec3[0] = std::make_unique<int>(1);
// vector of std::string
MyVector<std::string> vec4(5);
vec4[0] = "I am the very model of a modern major general...";
}
If the user of the vector want it to contain pointers, they can say so. There is no reason to force the user to use a pointer.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am learning the dynamic memory allocation process in c++.
1.How to declare dynamic memory allocation of an array without prior knowledge of the size?
2.Suppose I use a variable to dynamically allocate memory to the array but later on in the program the size of array is reduced.Will there be automatic de-allocation of memory?
If not then how to update it?
Please spare me if these are silly questions.If you answer please include an example program.
As Cheers and hth said in the comments, the best way is to use std::vector, it takes care of the memory management itself.
How to declare dynamic memory allocation of an array without prior knowledge of the size?
The idea is, you do not allocate any memory if you do not know the size, and when adding elements to it, you can increase the memory, see example below.
Implementing a class that works like std::vector:
vector uses two sizes, one is the size which is the number of elements your vector is currently holding, capacity is the number of elements which your vector can hold (memory is allocated for capacity)
Pre-requisites: I'm assuming that you know the basic memory allocation and de-allocation, that you can allocate memory using new operator, and de-allocate using delete operator.
Note: I'm implementing some methods for MyIntVector that uses only int array for simplicity, but you can always implement a templated class.
Implementation:
You can provide a default constructor for your class, which doesn't allocate any memory, sets the size and capacity to 0 (client programs can use this constructor, if the size is not known).
You can also provide a constructor which takes a size that will be used as the starting size, when creating the MyIntVector
Also provide a destructor to completely de-allocate the allocated memory.
class MyIntVector{
size_t _size;
size_t _capacity;
int* _data;
public:
MyIntVector(){
_size = 0;
_capacity = 0;
_data = nullptr;
}
MyIntVector(size_t size){
_size = size;
_capacity = size;
_data = new int[_capacity];
}
~MyIntVector(){
if (_data){
delete[] _data;
}
_data = nullptr;
_size = _capacity = 0;
}
};
Now, if you want to add some element to your MyIntVector, you can implement a push_back function, like std::vector does.
class MyIntVector{
//...
void push_back(int elem){
if (_size >= _capacity){
// Oops, we're out of memory, let's make room for this elem first
resize(_capacity > 0? _capcity * 2 : 10);
}
// Now, there's enough memory to hold this elem
_size++;
_data[_size - 1] = elem;
}
void resize(size_t newCapacity){
if (newCapacity != _capacity){
if (_size == 0){
_capacity = newCapacity;
_data = new int[_capacity];
}
else {
// create a temporary array to hold the elements of _data
int* temp = new int[_size];
for (size_t i = 0; i < _size; i++)
temp[i] = _data[i];
// de-allocate the memory of _data
delete[] _data;
// allocate memory in _data with newCapacity
_capacity = newCapacity;
_data = new int[_capacity];
// copy the elements of temporary array back in _data
for (size_t i = 0; i < _size; i++){
_data[i] = temp[i];
}
// done with the temporary array, de-allocate it.
delete[] temp;
temp = nullptr;
}
}
}
//...
};
push_back function:
The push_back function, that I've implemented in above example, it sees whether the new element can be added to the MyIntVector without any need to allocate any new memory or not, if not, it just increases the _size by 1 and copies the element. If there's a need for new memory, it calls the resize method with doubled capacity (in case, there's already some allocated memory there.) or some hard-coded value, say 10 (in case, where there's not any previously allocated memory)
resize function:
The resize function takes a newCapacity as argument, and allocates the required memory in _data, mainly it creates a temporary array to hold the elements of _data and then de-allocates the memory in _data, allocates a larger memory in _data, copies back the from temp to _data and de-allocates the temp array.
Note: This implementation of resize should only be used when increasing the _capacity, it should not be called for decreasing the _capacity
So, the idea is, that you can increase the size of the array, by using a temporary array for holding the elements, de-allocating the previous array, allocating a new array, and copying back the elements from temporary array. You can implement different methods that std::vector provides for your exercise.
If you don't want to de-allocate and re-allocate the memory every time you increase the capacity, you can always implement a Linked List, here's a tutorial for implementing a Linked List, but there's a drawback of Linked List, that you can't randomly access elements from the Linked List like you can from an array.
Suppose I use a variable to dynamically allocate memory to the array but later on in the program the size of array is reduced.Will there be automatic de-allocation of memory?
There's no automatic de-allocation of memory, you'll have to manually decrease the _capacity if you want.
You can add a pop_back method in your MyIntVector class to remove an element.
class MyIntVector{
// ...
int pop_back(){
if (_size == 0){
// You can throw some exception here if you want.
throw exception("No elements found");
}
_size--;
return _data[_size];
}
// ...
};
You can manually decrease the _capacity before returning the element.
You can also provide an implementation of subscript operator [] for your MyIntVector class to provide random access in the array.
If you do choose to dynamically allocate memory, you will need to use the operator new[] for an array, which is considered a different operator in c++ than new for non-array types.
1) Here is an example of how to dynamically allocate an array:
int length = 10;
int *myArray = new int[length];
// do something
myArray[0] = 42;
When you are done, you will need to release the memory with delete[]:
delete[] myArray;
2) No, there is no automatic de-allocation of dynamically allocated memory in C++ unless you are using smart pointers (What is a smart pointer and when should I use one?).
If you want to resize your array, you will have to do it manually:
delete[] myArray;
int newLength = 5;
myArray = new int[newLength];
As #frameworks pointed out, you will need the operator new[] to allocate memory for an array and you need to call delete[] to free that memory. If there is no delete[] for a new[], your program will leak memory. (If there is more than one delete[] called for a single new[], your program will segfault / crash.)
However, it is not always trivial to ensure that memory allocated with new[] (or new) gets always cleaned up by a corresponding delete[] (or delete), and only gets cleaned up once. That is especially true for code with complex control flow, code where pointers get passed around or situations where exceptions can be thrown between new[] and delete[].
In other words: Wherever there is a new, there probably is a leak.
So to save you all that trouble of manual memory management, use std::vector instead. This container takes care of the memory management for you.
Whenever you are tempted to write something like
int *myArray = new int[3];
//do something with myArray
delete[] myArray;
you should write
std::vector<int> myArray;
//do something with myArray
instead. You do not need a delete here and methods like std::vector::push_back() take care of the required size adjustments for the underlying structure, should it not provide enough space to accomodate all pushed values. You can also use std::vector::shrink_to_fit() to remove unused elements. (However, shrink_to_fit is a non-binding request to reduce the internal size. That is, results may vary between compilers.)
I'm trying to implement an array class which can be dynamically sized and it will allocate memory without initialising values. My question is relating to how I deallocate the memory later:
Can I implement my code in this way?:
template<typename Type>
class Array {
Type *values;
Array(int size) : values(new (size * sizeof(Type)) char()) {}
~Array() {
delete[] values;
}
}
Or will I need something like this?:
template<typename Type>
class Array {
Type *values;
void *memory;
Array(int size) : memory(new (size * sizeof(Type)) char()), values(memory), size(size) {}
~Array() {
delete[] memory;
}
}
NOTE!!!! I am aware that this will allocate memory without initialising any Type objects. This is the intended behavior of my code. Also the code above is not my complete implementation, it's only the code that will allocate and deallocate the memory because that is what I'm interested in with this question.
Upon further research I found that I should use malloc() and free() to do what I'm trying to do. Thank you to all answers and commenters.
You can use a Type* to make life easier, and use operator new to get memory without constructing objects.
Type* values; //No aliasing/casting issues
Array(int size) : values((Type*)::operator new(sizeof(Type) * size)) //...
~Array() { /*clean up extant objects*/ ::operator delete(values); }
Then you can use placement new and explicit destructor calls to manage the elements. Also, placement new doesn't allocate memory. It constructs an object at the specified address.
Placement new does not actually allocate any memory. It is merely syntax for calling a constructor with already-allocated memory.
In your destructor, you must manually call the destructors for each present element, then deallocate the memory in the same way it was allocated. Be very careful about exceptions.
You should probably use std::allocator<T>::allocate and std::allocator<T>::deallocate, but you could use malloc/free, new char[]/delete[] (char*)arr, or ::operator new/::operator delete.
I have
int * array=new int[2];
and I would like to free the memory of the last element, thus reducing the allocated memory to only 1 element. I tried to call
delete array+1;
but it gives error
*** glibc detected *** skuska:
free(): invalid pointer: 0x000000000065a020 *
Can this be done in C++03 without explicit reallocation?
Note: If I wanted to use a class instead a primitive datatype (like int), how can I free the memory so that the destructor of the class is called too?
Note2: I am trying to implement vector::pop_back
Don't use new[] expression for this. That's not how vector works. What you do is allocate a chunk of raw memory. You could use malloc for this, or you could use operator new, which is different from the new expression. This is essentially what the reserve() member function of std::vector does, assuming you've used the default allocator. It doesn't create any actual objects the way the new[] expression does.
When you want to construct an element, you use placement new, passing it a location somewhere in the raw memory you've allocated. When you want to destoy an element, you call its destructor directly. When you are done, instead of using the delete[] expression, you use operator delete if you used operator new, or you use free() if you used malloc.
Here's an example creating 10 objects, and destoying them in reverse order. I could destroy them in any order, but this is how you would do it in a vector implementation.
int main()
{
void * storage = malloc(sizeof(MyClass) * 10);
for (int i=0; i<10; ++i)
{
// this is placement new
new ((MyClass*)storage + i) MyClass;
}
for (int i=9; i>=0; --i)
{
// calling the destructor directly
((MyClass*)storage + i)->~MyClass();
}
free(storage);
}
pop_back would be implemented by simply calling the destructor of the last element, and decrementing the size member variable by 1. It wouldn't, shouldn't (and couldn't, without making a bunch of unnecessary copies) free any memory.
There is no such option. Only way to resize array is allocate new array with size old_size - 1, copy content of old array and then delete old array.
If you want free object memory why not create array of pointers?
MyClass **arr = new MyClass*[size];
for(int i = 0; i < size; i++)
arr[i] = new MyClass;
// ...
delete arr[size-1];
std::vector::pop_back doesn't reallocate anything — it simply updates the internal variable determining data size, reducing it by one. The old last element is still there in memory; the vector simply doesn't let you access it through its public API. *
This, as well as growing re-allocation being non-linear, is the basis of why std::vector::capacity() is not equivalent to std::vector::size().
So, if you're really trying to re-invent std::vector for whatever reason, the answer to your question about re-allocation is don't.
* Actually for non-primitive data types it's a little more complex, since such elements are semantically destroyed even though their memory will not be freed.
Since you are using C++03, you have access to the std::vector data type. Use that and it's one call:
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.erase(ary.begin() + (ary.size() - 1));
or
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.pop_back();
EDIT:
Why are you trying to re-invent the wheel? Just use vector::pop_back.
Anyway, the destructor is called on contained data types ONLY if the contained data type IS NOT a pointer. If it IS a pointer you must manually call delete on the object you want to delete, set it to nullptr or NULL (because attempting to call delete on a previously deleted object is bad, calling delete on a null pointer is a non-op), then call erase.
Alright, I think we all agree that what happens with the following code is undefined, depending on what is passed,
void deleteForMe(int* pointer)
{
delete[] pointer;
}
The pointer could be all sorts of different things, and so performing an unconditional delete[] on it is undefined. However, let's assume that we are indeed passing an array pointer,
int main()
{
int* arr = new int[5];
deleteForMe(arr);
return 0;
}
My question is, in this case where the pointer is an array, who is it that knows this? I mean, from the language/compiler's point of view, it has no idea whether or not arr is an array pointer versus a pointer to a single int. Heck, it doesn't even know whether arr was dynamically created. Yet, if I do the following instead,
int main()
{
int* num = new int(1);
deleteForMe(num);
return 0;
}
The OS is smart enough to only delete one int and not go on some type of 'killing spree' by deleting the rest of the memory beyond that point (contrast that with strlen and a non-\0-terminated string -- it will keep going until it hits 0).
So whose job is it to remember these things? Does the OS keep some type of record in the background? (I mean, I realise that I started this post by saying that what happens is undefined, but the fact is, the 'killing spree' scenario doesn't happen, so therefore in the practical world someone is remembering.)
One question that the answers given so far don't seem to address: if the runtime libraries (not the OS, really) can keep track of the number of things in the array, then why do we need the delete[] syntax at all? Why can't a single delete form be used to handle all deletes?
The answer to this goes back to C++'s roots as a C-compatible language (which it no longer really strives to be.) Stroustrup's philosophy was that the programmer should not have to pay for any features that they aren't using. If they're not using arrays, then they should not have to carry the cost of object arrays for every allocated chunk of memory.
That is, if your code simply does
Foo* foo = new Foo;
then the memory space that's allocated for foo shouldn't include any extra overhead that would be needed to support arrays of Foo.
Since only array allocations are set up to carry the extra array size information, you then need to tell the runtime libraries to look for that information when you delete the objects. That's why we need to use
delete[] bar;
instead of just
delete bar;
if bar is a pointer to an array.
For most of us (myself included), that fussiness about a few extra bytes of memory seems quaint these days. But there are still some situations where saving a few bytes (from what could be a very high number of memory blocks) can be important.
The compiler doesn't know it's an array, it's trusting the programmer. Deleting a pointer to a single int with delete [] would result in undefined behavior. Your second main() example is unsafe, even if it doesn't immediately crash.
The compiler does have to keep track of how many objects need to be deleted somehow. It may do this by over-allocating enough to store the array size. For more details, see the C++ Super FAQ.
Yes, the OS keeps some things in the 'background.' For example, if you run
int* num = new int[5];
the OS can allocate 4 extra bytes, store the size of the allocation in the first 4 bytes of the allocated memory and return an offset pointer (ie, it allocates memory spaces 1000 to 1024 but the pointer returned points to 1004, with locations 1000-1003 storing the size of the allocation). Then, when delete is called, it can look at 4 bytes before the pointer passed to it to find the size of the allocation.
I am sure that there are other ways of tracking the size of an allocation, but that's one option.
This is very similar to this question and it has many of the details your are looking for.
But suffice to say, it is not the job of the OS to track any of this. It's actually the runtime libraries or the underlying memory manager that will track the size of the array. This is usually done by allocating extra memory up front and storing the size of the array in that location (most use a head node).
This is viewable on some implementations by executing the following code
int* pArray = new int[5];
int size = *(pArray-1);
delete or delete[] would probably both free the memory allocated (memory pointed), but the big difference is that delete on an array won't call the destructor of each element of the array.
Anyway, mixing new/new[] and delete/delete[] is probably UB.
It doesn't know it's an array, that's why you have to supply delete[] instead of regular old delete.
I had a similar question to this. In C, you allocate memory with malloc() (or another similar function), and delete it with free(). There is only one malloc(), which simply allocates a certain number of bytes. There is only one free(), which simply takes a pointer as it's parameter.
So why is it that in C you can just hand over the pointer to free, but in C++ you must tell it whether it's an array or a single variable?
The answer, I've learned, has to do with class destructors.
If you allocate an instance of a class MyClass...
classes = new MyClass[3];
And delete it with delete, you may only get the destructor for the first instance of MyClass called. If you use delete[], you can be assured that the destructor will be called for all instances in the array.
THIS is the important difference. If you're simply working with standard types (e.g. int) you won't really see this issue. Plus, you should remember that behavior for using delete on new[] and delete[] on new is undefined--it may not work the same way on every compiler/system.
It's up to the runtime which is responsible for the memory allocation, in the same way that you can delete an array created with malloc in standard C using free. I think each compiler implements it differently. One common way is to allocate an extra cell for the array size.
However, the runtime is not smart enough to detect whether or not it is an array or a pointer, you have to inform it, and if you are mistaken, you either don't delete correctly (E.g., ptr instead of array), or you end up taking an unrelated value for the size and cause significant damage.
ONE OF THE approaches for compilers is to allocate a little more memory and store count of elements in the head element.
Example how it could be done:
Here
int* i = new int[4];
compiler will allocate sizeof(int)*5 bytes.
int *temp = malloc(sizeof(int)*5)
Will store 4 in first sizeof(int) bytes
*temp = 4;
and set i
i = temp + 1;
So i points to array of 4 elements, not 5.
And
delete[] i;
will be processed following way
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements if needed
... that are stored in temp + 1, temp + 2, ... temp + 4
free (temp)
Semantically, both versions of delete operator in C++ can "eat" any pointer; however, if a pointer to a single object is given to delete[], then UB will result, meaning anything may happen, including a system crash or nothing at all.
C++ requires the programmer to choose the proper version of the delete operator depending on the subject of deallocation: array or single object.
If the compiler could automatically determine whether a pointer passed to the delete operator was a pointer array, then there would be only one delete operator in C++, which would suffice for both cases.
Agree that the compiler doesn't know if it is an array or not. It is up to the programmer.
The compiler sometimes keep track of how many objects need to be deleted by over-allocating enough to store the array size, but not always necessary.
For a complete specification when extra storage is allocated, please refer to C++ ABI (how compilers are implemented): Itanium C++ ABI: Array Operator new Cookies
"undefined behaviour" simply means the language spec makes no gaurantees as to what will happen. It doesn't nessacerally mean that something bad will happen.
So whose job is it to remember these things? Does the OS keep some type of record in the background? (I mean, I realise that I started this post by saying that what happens is undefined, but the fact is, the 'killing spree' scenario doesn't happen, so therefore in the practical world someone is remembering.)
There are typically two layers here. The underlying memory manager and the C++ implementation.
Most memory managers were designed to meet the needs of the C language. In C the "free" function does not require the user to specify the size of the block. Therefore the memory manager will remember (among other things) the size of the block of memory that was allocated. This may be larger than the block the C++ implementation asked for. Typically the memory manager will store it's metadata before the allocated block of memory.
C++ has a culture of "you only pay for what you use". Therefore the C++ implementation will generally only remember the size of the array if it needs to do so for it's own purposes, typically because the type has a non-trival destructor.
So for types with a trivial destructor the implementation of "delete" and "delete []" is typically the same. The C++ implementation simply passes the pointer to the underlying memory manager. Something like
free(p)
On the other hand for types with a non-trivial destructor "delete" and "delete []" are likely to be different. "delete" would be somthing like (where T is the type that the pointer points to)
p->~T();
free(p);
While "delete []" would be something like.
size_t * pcount = ((size_t *)p)-1;
size_t count = *count;
for (size_t i=0;i<count;i++) {
p[i].~T();
}
char * pmemblock = ((char *)p) - max(sizeof(size_t),alignof(T));
free(pmemblock);
You cannot use delete for an array, and you cannot use delete [] for a non-array.
Hey ho well it depends of what you allocating with new[] expression when you allocate array of build in types or class / structure and you don't provide your constructor and destructor the operator will treat it as a size "sizeof(object)*numObjects" rather than object array therefore in this case number of allocated objects will not be stored anywhere, however if you allocate object array and you provide constructor and destructor in your object than behavior change, new expression will allocate 4 bytes more and store number of objects in first 4 bytes so the destructor for each one of them can be called and therefore new[] expression will return pointer shifted by 4 bytes forward, than when the memory is returned the delete[] expression will call a function template first, iterate through array of objects and call destructor for each one of them. I've created this simple code witch overloads new[] and delete[] expressions and provides a template function to deallocate memory and call destructor for each object if needed:
// overloaded new expression
void* operator new[]( size_t size )
{
// allocate 4 bytes more see comment below
int* ptr = (int*)malloc( size + 4 );
// set value stored at address to 0
// and shift pointer by 4 bytes to avoid situation that
// might arise where two memory blocks
// are adjacent and non-zero
*ptr = 0;
++ptr;
return ptr;
}
//////////////////////////////////////////
// overloaded delete expression
void static operator delete[]( void* ptr )
{
// decrement value of pointer to get the
// "Real Pointer Value"
int* realPtr = (int*)ptr;
--realPtr;
free( realPtr );
}
//////////////////////////////////////////
// Template used to call destructor if needed
// and call appropriate delete
template<class T>
void Deallocate( T* ptr )
{
int* instanceCount = (int*)ptr;
--instanceCount;
if(*instanceCount > 0) // if larger than 0 array is being deleted
{
// call destructor for each object
for(int i = 0; i < *instanceCount; i++)
{
ptr[i].~T();
}
// call delete passing instance count witch points
// to begin of array memory
::operator delete[]( instanceCount );
}
else
{
// single instance deleted call destructor
// and delete passing ptr
ptr->~T();
::operator delete[]( ptr );
}
}
// Replace calls to new and delete
#define MyNew ::new
#define MyDelete(ptr) Deallocate(ptr)
// structure with constructor/ destructor
struct StructureOne
{
StructureOne():
someInt(0)
{}
~StructureOne()
{
someInt = 0;
}
int someInt;
};
//////////////////////////////
// structure without constructor/ destructor
struct StructureTwo
{
int someInt;
};
//////////////////////////////
void main(void)
{
const unsigned int numElements = 30;
StructureOne* structOne = nullptr;
StructureTwo* structTwo = nullptr;
int* basicType = nullptr;
size_t ArraySize = 0;
/**********************************************************************/
// basic type array
// place break point here and in new expression
// check size and compare it with size passed
// in to new expression size will be the same
ArraySize = sizeof( int ) * numElements;
// this will be treated as size rather than object array as there is no
// constructor and destructor. value assigned to basicType pointer
// will be the same as value of "++ptr" in new expression
basicType = MyNew int[numElements];
// Place break point in template function to see the behavior
// destructors will not be called and it will be treated as
// single instance of size equal to "sizeof( int ) * numElements"
MyDelete( basicType );
/**********************************************************************/
// structure without constructor and destructor array
// behavior will be the same as with basic type
// place break point here and in new expression
// check size and compare it with size passed
// in to new expression size will be the same
ArraySize = sizeof( StructureTwo ) * numElements;
// this will be treated as size rather than object array as there is no
// constructor and destructor value assigned to structTwo pointer
// will be the same as value of "++ptr" in new expression
structTwo = MyNew StructureTwo[numElements];
// Place break point in template function to see the behavior
// destructors will not be called and it will be treated as
// single instance of size equal to "sizeof( StructureTwo ) * numElements"
MyDelete( structTwo );
/**********************************************************************/
// structure with constructor and destructor array
// place break point check size and compare it with size passed in
// new expression size in expression will be larger by 4 bytes
ArraySize = sizeof( StructureOne ) * numElements;
// value assigned to "structOne pointer" will be different
// of "++ptr" in new expression "shifted by another 4 bytes"
structOne = MyNew StructureOne[numElements];
// Place break point in template function to see the behavior
// destructors will be called for each array object
MyDelete( structOne );
}
///////////////////////////////////////////
just define a destructor inside a class and execute your code with both syntax
delete pointer
delete [] pointer
according to the output u can find the solutions
The answer:
int* pArray = new int[5];
int size = *(pArray-1);
Posted above is not correct and produces invalid value.
The "-1"counts elements
On 64 bit Windows OS the correct buffer size resides in Ptr - 4 bytes address