I'd need a class like std::auto_ptr for an array of unsigned char*, allocated with new[]. But auto_ptr only calls delete and not delete[], so i can't use it.
I also need to have a function which creates and returns the array. I came out with my own implementation within a class ArrayDeleter, which i use like in this example:
#include <Utils/ArrayDeleter.hxx>
typedef Utils::ArrayDeleter<unsigned char> Bytes;
void f()
{
// Create array with new
unsigned char* xBytes = new unsigned char[10];
// pass array to constructor of ArrayDeleter and
// wrap it into auto_ptr
return std::auto_ptr<Bytes>(new Bytes(xBytes));
}
...
// usage of return value
{
auto_ptr<Bytes> xBytes(f());
}// unsigned char* is destroyed with delete[] in destructor of ArrayDeleter
Is there a more elegant way to solve this? (Even using another "popular" library)
Boost has a variety of auto-pointers, including ones for arrays. Have you considered if std::vector is sufficient? Vectors are guaranteed to be contiguous in memory, and if you know the size and allocate memory ahead of time via reserve() or resize(), the location in memory will not change.
I then have to call a methods that takes unsigned char* as argument.
std::vector<unsigned char> vec;
.
.
.
legacy_function(&vec[0], vec.size());
How about using std::basic_string<unsigned char>? Or maybe std::vector<unsigned char>?
You're talking about an array of int, not complex C++ types that have a destructor.
For such an array calling delete[] is equivalent to calling delete. So there's no problem to use std::auto_ptr.
The method you suggest is very barbaric IMHO. You actually allocate memory twice: once for the needed array, and then you also allocate an instance of ArrayDeleter, which encapsulates the pointer to the allocated array.
The drawbacks of such a method are:
Worse performance. Heap operations are heavy. Also they have significant memory overhead.
Slower access. To access an element of your array via the std::auto_ptr<Bytes> the compiler will generate two indirections: one to get your Bytes object, and the other to access the element.
In simple words: std::auto_ptr has a pointer to Bytes object, which has a pointer to the array.
Worse error/exception consistency. Imagine what if the operator new fails to allocate the Bytes object. It'll generate an exception, which may be handled. But at this point you've already allocated the array. And this allocation will be lost.
I'd do one of the following:
If you're talking about an ordinary type - just use std::auto_ptr<type>. This should do the work. However you should check it with your compiler.
For complex types: you may create your own wrapper instead of the std::auto_ptr.
Another variant: similar to what you did. However you should get rid of the extra memory allocations and indirections.
Related
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).
I'm dabbling around with C++ and trying to wrap my head around the pointer thing. When creating an array of objects, is it better to create the array of the object type or of pointers?
For instance:
Block grid[size]; or Block* grid[size];
From what I've been reading I was under the impression that when using objects it's almost always better to use pointers to save memory? Eventually I'm going to create a dynamically allocated 2D array of these objects, and I'm wondering if it's worth hassling to try and store them as pointers in the multidimensional array.
NOTE: I have been told to look into 2D vectors, when it comes to dynamically creating them and allocating them I'm struggling just as much as with these arrays.
Thanks in advance!
I think you are mixing something. A classic C-array is a pointer pointing to the first element. What you think of are classes which are expensive when they get (deep-)copied while calling a function or similar. These expensive function arguments (strings, vectors, and similar) are better be passed as references (or pointers).
'Modern C++' provides you with enough utility that you shouldnt use any allocation on your own, if you are not writing your own containers. You usually use pointers to point to things, that you do not own in a context. I also recommend to not use classic C-arrays anymore. Use
array<Block, size> grid; // compile-time constant size
instead of
Block grid[size]; // compile-time constant size
array<> will try to be on the stack. If size is not known to compile time, you have to allocate the memory on the heap. The STL calls these heap-arrays vector instead
vector<Block> grid(size); // runtime variable size
if (grid.size() > 0)
cout << grid[0]; // use grid like an array
The old C-style way for heap arrays was to allocate memory manually and free it after you do not need it anymore. This is very error-prone and should be avoided unless you know what you do.
As mentioned the difference to plain old arrays (which are pointers) is when calling a function. Before you had to pass a pointer and potentially the size of the array
void fancy_old_function(Block* grid, size_t size) // BAD practise
{
// do things
}
// ...
{
Block grid[size];
fancy_old_function(grid, size); // error prone
...
// maybe alot later
fancy_old_function(grid, 13); // ohoh! 13 < size?
}
In C++ and with big objects you should pass these as a reference (or make it a pointer) otherwise your vector gets deep copied.
void fancy_new_function(vector<Block>& grid) // GOOD
{
// do fancy stuff an potentially change grid
}
The drawback is now, that we have different signatures for dynamic and static arrays:
template <size_t N>
void fancy_new_function(array<Block, N>& grid) // GOOD
{
// do fancy stuff an potentially change grid
}
A huge improvement to classic C-arrays is, that we know the size of an array implicitly at all times.
You can call your fancy_new_function like this:
{
array<Block,size> grid1;
fancy_new_function(grid1); // size is implicitly deduced
// or use grid1.size();
vector<Block> grid2(size);
fancy_new_function(grid2); // developer can use grid2.size()
}
HTH
I would use Block grid[size], because why would you create an array of pointers (the only reason I can think of is for an array with unknown size at compile time) In terms of memory, the pointers are a bit more expensive, because their address and their content is stored (on the stack and on the heap respectively). And you can't forget to deallocate them when you are done with them, otherwise you will get a memory leak.
The better alternative would be std::array<Block, size> grid, or even std::vector<Block> grid.
std::vector is like an std::array, but its dynamic, without a fixed size (so you can change it a runtime, for example).
Assuming this is in a function, it doesn't 'save' memory.
One implementation uses more stack memory.
The other uses less stack memory, but uses more heap.
This entirely uses the stack:
Block grid[size];
This uses the stack to store your pointers to objects.
The memory used to store the objects is the heap:
Block* grid[size];
However, if these are global declarations, then yes, this:
Block grid[size];
does potentially waste memory because it is allocated for the lifetime of your application, and cannot be deallocated/resized.
The answer to "better" depends upon how you would the array.
If Block is small (2-8 bytes) or you need to use every element of grid, you'd be better off doing
Block grid [size] ;
In almost all cases.
Suppose sizeof (Block) > 512 and you do not use all the elements of grid and
const int size = 10 ;
you'd probably be better off with
Block grid [size] ;
Would probably make the most sense. On the other hand, suppose
const in size = 2000000 ;
then
Block *grid [size] ;
makes more sense.
Better is rather a matter of taste :-)
An array of objects may be simpler to use for simple use cases because you create and destroy the full array at once. It look a little more C++ idiomatic.
The exception I can think would be:
performance reasons with expensive to create objects. Here you only create an array for pointers with the maximum size and create objects when you need them
polymorphism with derived classes. IMHO this is the best use case for using arrays of pointers. Because if you try to copy a derived object into its base class, you will get object slicing: the base class copy will loose all attributes that are only present in derived class. So in that case, you create an array to pointers to the base class (it can even be abstract) and populate it with concrete implementations. And you can manipulate any object in the array with the virtual methods from the base class.
class Tool
{
public:
Tool();
~Tool();
private:
char **s;
};
char *s1[]={"hello","world"};
How can I initialize s and make it same as s1?
s={"hello","world"}
doesn't seem to work.
While you could use a std::vector<std::string>, I feel it's more beneficial to you to directly answer your question.
char** s is a pointer to a pointer; possibly a pointer to the first pointer in an array of pointers.
char* s1[] is an array of pointers to const data (and should have actually been made const).
If you want s to work similarly to s1, you first need to allocate the array of pointers, which is the reason std::vector was recommended by others. You could do it yourself with new, but you have to release the allocated memory at some point. Using new directly is prone to leaks. std::vector will release its allocated memory when the object is destructed. You too could call delete[] in your destructor if you wanted to.
When your array has been allocated, you then need to std::copy the array of pointers in s1 to the array of pointers in s. It's not a single assign operation.
Is there a fast (CPU) way to cast a char array into a std::vector<char>?
My function looks like this:
void someFunction(char* data, int size)
{
// Now here I need to make the std::vector<char>
// using the data and size.
}
You can't "cast" anything here, but you can easily construct a vector from the C string:
std::vector<char> v(data, data + size);
This will create a copy though.
The general rule with STL containers is that they make copies of their contents. With C++11, there are special ways of moving elements into a container (for example, the emplace_back() member function of std::vector), but in your example, the elements are char objects, so you are still going to copy each of the size char objects.
Think of a std::vector as a wrapper of a pointer to an array together with the length of the array. The closest equivalent of "casting a char * to a std::vector<char>" is to swap out the vector's pointer and length with a given pointer and length however the length is specified (two possibilities are a pointer to one past the end element or a size_t value). There is no standard member function of std::vector that you can use to swap its internal data with a given pointer and length.
This is for good reason, though. std::vector implements ownership semantics for every element that it contains. Its underlying array is allocated with some allocator (the second template parameter), which is std::allocator by default. If you were allowed to swap out the internal members, then you would need to ensure that the same set of heap allocation routines were used. Also, your STL implementation would need to fix the method of storing "length" of the vector rather than leaving this detail unspecified. In the world of OOP, specifying more details than necessary is generally frowned upon because it can lead to higher coupling.
But, assume that such a member function exists for your STL implementation. In your example, you simply do not know how data was allocated, so you could inadvertently give a std::vector a pointer to heap memory that was not allocated with the expected allocator. For example, data could have been allocated with malloc whereas the vector could be freeing the memory with delete. Using mismatched allocation and deallocation routines leads to Undefined Behavior. You might require that someFunction() only accept data allocated with a particular allocation routine, but this is specifying more details than necessary again.
Hopefully I have made my case that a std::vector member function that swaps out the internal data members is not a good idea. If you really need a std::vector<char> from data and size, you should construct one with:
std::vector<char> vec(data, data + 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;