I need to resize an array of pointers - c++

Lets say i want to resize an array of int pointers, i have a function that looks like this
template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
The problems begin when i try and resize an array of elements that were created with the "new" keyword (even though the data itself inside the class is POD) because the delete[] triggers their deconstructor which then leaves the new array with pointers to objects that dont exist anymore. So.. even though the objects were created with "new", cant i just use the free command to get rid of the old array? or somehow delete the array without triggering the deconstructor of each member?

Use a std::vector.
EDIT: by popular demand, an explanation of why the OP's code does not work.
The code:
template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
Here arr is a pointer passed by value. Assigning to arr at the end only updates the local copy of the actual argument. So after this the actual argument, in the calling code, points to an array that has been deleted, whith pretty catastrophic result!
It could be sort of rescued by passing that pointer by reference:
template<typename T>
static void Resize(T*& arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
But this is still pretty fragile code.
For example, the caller needs to keep track of the array size.
With a std::vector called a, the resize call would instead look like
a.resize( newSize )
and in contrast to the DIY solution, when newSize is larger, those extra elements of the vector are nulled (which is a bit safer than leaving them as indeterminate values).
A std::vector can be indexed just like a raw array. See your C++ textbook about more details of how to use it. If you don't already have a C++ textbook, do get one: for most people it's just an impractical proposition to learn C++ from articles and Q/A on the web.

For what it's worth, what you're trying to do isn't a terribly bad thing, and there are times it makes sense, but it's simply not supported by the interface provided by new and delete (or new[] and delete[]). As others have said, it is supported by malloc, free, and realloc (with the caveat that realloc will copy the pointer values on reallocation, but won't guarantee that the pointers in the new area are initialized to anything useful, like NULL).
So, without further ado, the easiest answer that will work for almost everybody is to use a std::vector<int> instead of trying to manage the memory yourself. The vector has the ability to resize, and when it does it will copy things that need copying. std::vector exists to provide a "resizable array" and manage the memory for you. Actually, if you want a container of pointers, you're best off using either a std::vector<std::unique_ptr<T>>/std::vector<std::shared_ptr<T>> (in C++11) or something from Boost Pointer Container.
For what it's worth, the original STL did not use new[] or delete[] to implement std::vector<T>. Often, the operating system gives far more memory than you ask for. For instance, if I try to malloc 16 bytes, the block I get back may well be 1024 bytes. I can use that to store four 32 bit integers. When I run out of space, I may ask for 32 bytes, and get a different block of 1024 bytes, which I can copy my four integers to. But why go through the trouble of asking for a new block to hold my integers, when the original block was actually large enough to begin with? Unfortunately, new[] and delete[] don't provide a way to say "give me a block that's at least this large, and by the way here's a block that might already be big enough." realloc kind of does. Facebook Folly includes a std::vector-like container that doesn't use new[] or delete[] (note that it doesn't use realloc either, because that usually won't work with containers of objects; instead it uses malloc and the non-standard function malloc_usable_size), and Firefox goes through the trouble to manage memory in a similar manner.
Even so, I would discourage trying to get tricky. std::vector has a lot of satisfied users.

I think that making all elements in array point to NULL before deleting should do the job. But if you can use STL then std::vector would make your life much easier (as Alf suggested :P).

Related

Use a ::std::vector for array creation

I want to grow a ::std::vector at runtime, like that:
::std::vector<int> i;
i.push_back(100);
i.push_back(10);
At some point, the vector is finished, and i do not need the extra functionality ::std::vector provides any more, so I want to convert it to a C-Array:
int* v = i.data();
Because I will do that more than once, I want to deallocate all the heap memory ::std::vector reserved, but I want to keep the data, like that (pseudo-code):
free(/*everything from ::std::vector but the list*/);
Can anybody give me a few pointers on that?
Thanks in advance,
Jack
In all the implementations I have seen, the allocated part of a vector is... the array itself. If you know that it will no longer grow, you can try to shrink it, to release possibly unused memory:
i.shrink_to_fit();
int* v = i.data();
Of course, nothing guarantees that the implementation will do anything, but the only foolproof alternative would be to allocated a new array, move data from the vector to the array and clear the vector.
int *v = new int[i.size];
memcpy(v, i.data, i.size * sizeof(int));
i.clear();
But I really doubt that you will have a major gain that way...
You can use the contents of a std::vector as a C array without the need to copy or release anything. Just make sure that std::vector outlives the need for your pointer to be valid (and that further modifications which could trigger a reallocation are done on the vector itself).
When you obtain a pointer to internal storage through data() you're not actually allocating anything, just referring to the already allocated memory.
The only additional precaution you could use to save memory is to use shrink_to_fit() to release any excess memory used as spare capacity (though it's not guaranteed).
You have two options:
Keep data in vector, but call shrink_to_fit. All overhead you'll have - is an extra pointer (to the vector end). It is available since C++ 11
Copy data to an external array and destroy the vector object:
Here is the example:
std::vector<int> vec;
// fill vector
std::unique_ptr<int[]> arr(new int[vec.size()]);
std::copy(vec.begin(), vec.end(), arr.get());

Can I pass a pointer to a pointer, allocate memory, then pass it back?

Consider the following code. This works for allocating a single array, but what if you needed to allocate a two dimensional array? How would you go about doing this?
#include <iostream>
void alloc(int **num)
{
*num = new int[5];
*num[0] = 5;
}
int main()
{
int *num;
alloc(&num);
std::cout << num[0] << std::endl;
delete [] num;
}
My goal is to pass **char into the function and have it allocated. Is this possible?
what if you needed to allocate a two dimensional array?
My goal is to pass **char into function and have it allocated.
So, what you want is a pointer to an array of pointers (each to an array)? That is different from an 2D array, although often treated as such for simplicity.
Just like you added an additional layer of indirection when you allocated that single array, you can add a layer of indirection to allocate an array of pointers, and the pointed to arrays of integers.
So, you could write a function like void alloc(int ***num). Yes, this is possible, but not very good design.
But using a pointer for the indirection makes the syntax more complex, and has the risk of a user passing a null pointer to the function. Instead, a better alternative would be to use a reference: void alloc(int **&num).
Since the function allocates something and "returns a pointer", it would make more sense to actually return the pointer: int** alloc(). Much prettier, isn't it? Less indirection is better.
Finally, there is the problem that a user of the function has to know how to delete the allocated memory. Was it allocated with new or new[]? Maybe even malloc? Or does the function perhaps return a pointer to a static object, that must not be deleted? The caller of the function cannot know that unless it is documented separately.
Also, what if one of the allocation fails? There will be an exception, and the earlier allocations will leak.
The C++ way to solve the above 2 problems is to use a RAII container to manage the memory. Since you apparently want to have an array with pointers to arrays, there is a ready made solution in the standard library for you: return a std::vector<std::vector<int>>. If you instead want a proper non-jagged 2D array i.e. a matrix, then you may want to write a custom RAII container for that, possibly using a flat std::vector<int> for the implementation. Note that a third party may already have implemented such container.
Your code looks like C to me. In C++ I would (maybe) use custom types and not do any manual dynamic allocation. For example
typedef std::vector<int> Row;
typedef std::vector<Row> Matrix;
Matrix initMatrix(int nRows,int nCols) {
return Matrix(nRows,Row(nCols));
}
well in that case you dont even need a function but you can just call the constructor (and let array allocate the memory for you).

C++ Deallocate exact size of memory

I've thought about how I can improve the performance of reading of a list sort by an (unsigned) integer that is read in at the program start and won't change until the program exits. I thought about different possibilities but then I got an idea and I'd like to know if that's possible and if not, why not - because in my theory it should be possible for the computer.
I have a list with something like 10.000 entries, every entry has an unique ID (an the unique ID is not 0). Now what about allocating memory with the size object* pList = new(sizeof(object) * max_unique_id) and then deleting all the unused memory (check what unique id is not existing and free the memory at the position with the size sizeof(object))... you would be using only the needed memory and you could just access to a list entry with pList[unique_id] -> would be really, really fast... but you cannot delete a single element in a dynamic allocated array :/ At the program termination you can of course free all the elements, it's no problem to safe the pointer + sizes in a std::vector or sth like that.
That's why I'm asking if my theory is incorrect or if the system just does not allow it or where the problem is.
No, you can't control memory like that. However, it IS possible to cheat a little bit. If you are allocating big chunks of memory, you can make your own memory pool. That way, you can create the holes yourself and use that memory for other parts of your program.
I wouldn't recommend it though, as you may have issues with strict aliasing, as well as having to deal with more complexity in your code.
Rewinding just a little, you are forgetting about caching effects, which are significant. Keeping your objects packed closely together will likely have more effect on speed than making the lookup faster.
To achieve this you could use a simple hash to look up your objects, or you could just make a sparse index array of 16-bit indices.
You can, (though I have no idea why you want to), but you will have to write it as your own custom memory allocation and deallocation routine or class. Using the standard C++ library out of the box, you can't.
See some of the interfaces for allocating memory in C++
void* operator new ( std::size_t );
void* operator new[]( std::size_t );
void* operator new ( std::size_t, const std::nothrow_t&);
void* operator new[]( std::size_t, const std::nothrow_t&);
Taking void* operator new[]( std::size_t ); for example. There is absolutely no way the this routine knows how many objects are stored in the memory region that will be returned.
Same with it's matching function
void operator delete[]( void* ptr );
it only takes a void pointer, there is absolutely no way it knows how many you want to delete. The memory allocator that provided memory starting with that block pointed by ptr magically knows the size it allocated, and hence deletes it appropriately
Use placement new.
object* pList = new(sizeof(object) * max_unique_id)
Do not do this. new is NOT malloc. But you also cannot do this instead:
object* pList = new object[max_unique_id];
delete object[1];
C++ does not allow to delete individually allocated elements of a dyanmically allocated array with a simple delete.
C++ allows you to create an object in a pre-allocated memory space by using placement new. In this case, you must manually call the constructor with a call to placement new and the destructor.
Reference: Malloc and constructors
A* a = (A*)malloc(sizeof(A));
new (a) A();
a->~A();
free(a);
In other words, supply the exact place where you want a specific object to be created. I would suggest that you use a loop:
// Allocate the space using malloc()
object* pList = std::malloc(sizeof(object) * max_unique_id);
// Allocate using a loop. I would not trust a parallelization of this code.
// Doing memory allocation in parallel without the proper locks and stuff
// is probably wrong.
for (auto i = 0; i < max_unique_id; ++i) {
// Supply the point as the argument to placement new.
new (&pList[i]) object(/* arguments go here */);
}
Then, when you're done using a certain object, say i = 20...
// Select the object
object* todelete_object = pList[i];
// Manually call the destructor.
todelete_object->~object()
// Now, free the memory.
std::free(todelete_object);
I use std::malloc() and std::free() as defined in the C++-style C standard library includes.

Where exactly in memory is count of allocated memory thats being used by delete?

int* Array;
Array = new int[10];
delete[] Array;
The delete knows the count of allocated memory. I Googled that it stores it in memory, but it's compiler dependent. Is there anyway to use get this count?
Actually, the heap knows how large each allocation is. However, that's not something that you can access easily, and it is only guaranteed to be greater than or equal to the amount requested. Sometimes more is allocated for the benefit of byte alignment.
As Ben said though, the implementation does know in certain circumstances how many objects are in the array so that their destructors can be called.
There is no standard way to retrieve the number of elements after construction. In fact, for an int array, it is probably NOT stored anywhere. The count is only necessary for arrays of elements with non-trivial destructors, so that delete[] can call the right number of destructors. In your example, there aren't any destructor calls, since int doesn't have a destructor.
There's no way to get the number of elements of a dynamically allocated array after you allocate it.
The one way to rule them all
However, you can store it beforehand:
int* Array;
size_t len = 10;
Array = new int[len];
delete[] Array;
Custom class
If you don't like that, you could create your own class:
class IntArray
{
public:
int* data;
size_t length;
IntArray(size_t);
~IntArray();
};
IntArray::IntArray(size_t len)
{
length = len;
data = new int[len];
}
IntArray::~IntArray()
{
length = 0;
delete data;
data = NULL;
}
std::vector
The method I recommend is to use std::vector:
std::vector<int> Array (10, 0);
You can use it just like a regular array... with extra features:
for(size_t i = 0; i < Array.size(); ++i)
Array[i] = i;
There are likely one or two counts of the number of elements in such an allocation depending upon the type and the implementation that you are using though you can't really access them in the way you probably want.
The first is the accounting information stored by the actual memory manager that you are using (the library that provides malloc). It will store that a record of some size has been allocated in the free store of the system (heap or anonymous memory allocation are both possible with the glibc malloc for example). This space will be at least as large as the data you are trying to store (sizeof(int)*count+delta where delta is the C++ compiler's tracking information I talk about below), but it could also be larger, even significantly so.
The second count is a value kept by the compiler that tells it how to call destructors on all the elements in the array (the whole magic of RAII), but that value is not accessible and could probably even be done without directly storing the information, though that would be unlikely.
As others have said, if you need to track the information on allocation size you probably want to use a vector, you can even use it as an actual array for the purpose of pointer math if need be (see http://www.cplusplus.com/reference/stl/vector/ for more on this).
Who says that there actually is one?
This stuff depends on the implementation and as such is uninteresting for you, me or whoever wants to know it.
C++ generally intentionally doesn't allow you access to that information, because arrays are simple types that do not keep that information associated with them. Ultimately that information must be stored, but the compiler is free to figure out how, where, and when by the C++ standards to allow for optimization in the assembly.
Basically, either store it yourself somewhere, or (better, most of the time), use std::vector.
No, you need to keep track of it yourself if you need to know.
Many people like using a std::vector if it's not a fixed size. std::vector keeps track of the size allocated for you.

Define array, then change its size

I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;