I think this is an easy issue, but it's driving me crazy: I want to return multiple arrays from one method, for which the calling method does not know their size in advance. So I have to create those Arrays inside the method (in contrast to just filling them) and I am not able to return them using return.
So what I would want is a method signature like this:
void giveMeArray(int[] *anArray)
Method signature has only one parameter to simplify the examples, please assume I could also have a signature like
void giveMeArrays(int[] *anArray, float[] *anotherArray)
Inside that method giveMeArray I would construct the array with
*anArray = new int[5];
and I would call that method using
int[] result;
giveMeArray(&result);
However, all this (starting with the method signature) is at least syntactically wrong. Please excuse that I don't have the compiler errors at hand by now, I'm pretty sure some of you will know what's wrong.
EDIT I know that std::vector would be the best (meaning cleanest) approach. However, folks, that wasn't the question.
Return a single vector (this is C++ afterall)
void giveMeArray(std::vector<int>& anArray)
{
anArray = std::vecotr<int>(5);
}
Return a vector of vectors:
void giveMeArray(std::vector<std::vector<int> >& anArray)
void giveMeArray(int **anArray);
int *result;
giveMeArray(&result);
std::vector<int> giveMeArray() {
std::vector<int> ret;
ret.resize(5);
return ret;
}
Nice resource cleanup, bounds checking in debug modes, etc. Good for all the family.
Consider wrapping the arrays in a class or struct.
struct Arrays {
int *ints;
int intCount;
double *doubles;
int doubleCount;
};
Arrays giveMeArrays() {
Arrays arrays;
arrays.ints = new int[10];
arrays.intCount = 10;
arrays.doubles = new double[20];
arrays.doubleCount = 20;
return arrays;
}
An alternative is to use a std::pair<> or a std::tuple<>, but in my experience any use of those eventually becomes a named type. The fact that they are all part of the result of your function suggests they may have enough coherence to be an object. Having a user-defined type makes it easier to pass the data around, and so to refactor code. You may even find that giveMeArrays() becomes a member function of this object.
Replacing ints/intCount with std::vector<int> would be better, if possible. If not, you may want to give Arrays more responsibility for memory management, disable copying while allowing moving, and so forth.
Related
I have a function that returns a void*. Right now, when this function is completed, a UINT16* array is returned as the void*. The UINT16 array is created at the start of the method, but now I need a way to determine the type of array and create that type instead. For example, some data processing occurs and determines that an array of type int should be created, so an int array is created and returned. Other types like double and byte can also be created.
How do I go about achieving this?
My current code has
UINT16* data_out = new UINT16[arraySize];
I know I can create a large if/else or switch statement, but I'm wondering if there is a better way.
Something like that perhaps ?
This will not work, but thanks for the upvote. In fact it could work, but you'll have to know the type returned by Foo to be able to use it. But the type is determined inside Foo, that's a serious conception drawback. You should rethink the way you want this to work.
enum class ArrayType
{
Int,
Double
};
template <typename T>
T* CreateArray(size_t size)
{
T* t = new T[size];
return t;
}
void* Foo(param1, param2, etc..)
{
size_t size;
ArrayType type;
.. Do things to determine the type
switch(type)
{
case ArrayType::Int:
return CreateArray<int>(size);
case ArrayType::Double:
return CreateArray<double>(size);
default:
return 0;
}
return 0;
}
Uhm... sorry if this is more of a question than a comment... :| I can't comment rn.
If you want a core solution, you could create a linked list class that has different type outlets. Basically, instead of having just an UINT_64* next;, you would have:
int* nextInt;
double* nextDouble;
And so on and so forth. Then, if you want to tag a double along, you could just use the nextDouble outlet. To find which outlet to go to, just check if the int is pointing to anything; if not, go next. I know this seems like a REALLY annoying and bulky option, but I suppose it does the job.
I'm not sure why you have to use a practically untyped return value using void*, but let's suppose that there are reasons for it.
There are actually two issues, namely creating the array and using it then.
When creating an array of different types based on some logic, you somehow have to deal with if or switch(); how else would you express the logic determining the desired result type? But, if you like, you could also use something like result = malloc(nrOfItems*sizeOfItem), and determine sizeOfItem on any logic you like, even based on arithmetic calculations.
The more interesting or critical thing is how the caller shall use the result of the respective function, as accessing the elements of an array requires knowledge about the type or the size of the elements in it.
Suppose, for example, the following code:
void* getSomeItems() {
if (std::rand() > 100000)
return new char[200];
else
return new double[200];
}
int main() {
void* someItems = getSomeItems();
double c = ((double*)someItems)[199]; // Critical!
// how shall we know if element type is double?
// if rand() decided to create items of type char,
// this code accesses non allocated memory
...
So, unless your function can give back the information on which type has been created (and actually also the size of the array), the return value is almost needless.
I'd suggest not to use void* for this. If you know the type before calling the function, you could use templates, vectors, or other things. If you do not know type and/or size before calling, return a structure that - besides the allocated array - also provides type/size information.
BTW: do not forget to delete[] / free the result at the end.
Void * functions can be fun and do some very interesting things... (Sorry for linking a previous answer of mine, but it's the first example which came to me.) But they aren't safe, and have zero type checking...
So in your case, you only need a simple template function, and the auto keyword. Something like:
#include <iostream>
#include <iomanip>
template <typename T>
T * returnAnArray (int size) {
T * data_out = new T[size];
return data_out;
}
int main() {
int size = 3;
auto array = returnAnArray<double>(3);
for(int i=0;i<size;++i)
array[i] = 0;
for(int i=0;i<size;++i){
std::cout << std::setprecision(2);
std::cout << array[i] << std::endl;
}
delete [] array;
return 0;
}
I did have some fun, and did create a void * function:
template <typename T>
void * returnVoidPointerToArray(int size) {
return new T[size];
}
The function, when used, must be cast for it could return something:
auto chArray = (char*)returnVoidPointerToArray<char>(size);
But the output looks like:
5.00
5.00
5.00
ggg
ggg
ggg
Program ended with exit code: 0
Note how double are a single value, but the same function also initialized a 2d array of characters... Cool, right? Albeit, it's a dirtier, different way of templating functions.
And, like the commenter said, probably a good idea to use unique pointers. :)
And like the other commenter said, I cast the array to char* and got a char* array. :)
I'm moving from Objective-C to C++ and am not sure what vectors are. I've read documentation about them, I'm not quite clear though. How would you explain C++ vectors using Objective-C analogies?
They're pretty similar to NSMutableArrays but vector is a template class and so can be instanciated for any (standard-template-library compatible) type. NSArrays always hold NSObjects.
That is, assuming you mean std::vector.
They're like NSMutableArrays but can hold any data type - pointer or not. However, each vector can only ever hold one type at a time. Also as it's C++ there are fewer functions e.g. no plist loading/saving.
A C++ vector (presumably you mean something like std::vector) is basically an NSArray, except it holds any type you want (which is the template parameter, e.g. a std::vector<int> holds ints). Of course, it doesn't do memory management (which NSArray does), because arbitrary types aren't retain-counted. So for example a std::vector<id> would be rather inappropriate (assuming Obj-C++).
NSArray is a wrapper around CFArray. CFArray can store any data type.
I don't know much about C++, but it sounds like CFArray can do everything you'd use a vector for? When creating a CFArray you give it a CFArrayCallBacks pointer, which contains any logic that is specific to the data type being stored.
Of course, you could always just rename your Obj-C file to *.mm, and mix C++ into your objective-c.
http://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFArrayRef/Reference/reference.html
In C++ an Array is basically just a pointer to a contiguous block of data---a series of elements. It offers no built-in methods, or higher functionality.
int intArr[] = {0,1,2,3};
is the same as
int *intArr = (int *)malloc(4*sizeof(int));
for(int i = 0; i < 4; i++) { intArr[i] = i; }
A vector (std::vector), on the other hand, is a container for elements (basically like an array) which also offers additional built in methods (see: http://www.cplusplus.com/reference/stl/vector/) such as
vector<int> intArr;
for(int i = 0; i < 4; i++) { intArr.push_back(i); }
// this yields the same content; i.e. intArr = {0,1,2,3}
Both arrays and vectors can be used on any type of objects, int, double, 'MySpacePirateWizardClass' etc. The big bonus of vectors is the additional functionality from built-in functions like:
int arrSize = intArr.size(); // vector also includes useful information
int *firstElement = intArr.begin(); // methods for creating pointers to elements
intArr.delete(0); // modify elements
intArr.insert(0, 2); // modify vector
// now: intArr = {2,1,2,3}
etc etc.
When I know I'm not going to be short on space (or looking at massive amounts of data), I always use vectors because they're so more convenient (even just the size() method alone is reason enough).
Think about vectors as advanced arrays.
If you are new to C++, this page will be your best friend:
http://www.cplusplus.com/reference/stl/vector/
I would like to build a function that takes a multidimensional array and prints it like a grid. I'm having trouble with it because c++ doesn't allow a function to have a multidimensional array argument unless you specify its length. There is a question about it on here, that was answered using vectors. I haven't learned how to use vectors yet, so please don't use them in an answer, or at least provide a good tutorial on them if you do.
Anyway, I was wondering if it's possible to return an array in c++... I started programming with javascript, so the first solution I thought of was to do something like
int gen(int len){
return int arr(int a[][len]){
cout << a[0][0];
};
}
I knew it wouldn't work, tried it, and wasn't surprised when it didn't. Is there a way to do something like this though?
In C++ you can pass array by reference. With making an array a template, it's possible to receive any length in the function. For example,
template<size_t SIZE1>
void print (int (&arr)[SIZE1])
{ ... }
template<size_t SIZE1, size_t SIZE2>
void print (int (&arr)[SIZE1][SIZE2])
{ ... }
template<size_t SIZE1, size_t SIZE2, size_t SIZE3>
void print (int (&arr)[SIZE1][SIZE2][SIZE3])
{ ... }
This pattern will internally create a unique function for every different size of array. It offers ease of use, but may increase the code size.
You have to know the size of the array, there's no way around it. std::vector is the correct way to solve this, and you can find a good reference here. That allows passing only the vector, as it knows its own length and the function can ask it, making it similar to what you're used to from Javascript.
Otherwise, you must pass the size of the array to the function one way or another.
One way is using templates, but that would not work on dynamic arrays (and is a bit wasteful, as it creates a copy of the function per each array size used). The other is just adding an additional parameter to the function, with the size.
I'm trying to create an array and pass it to functions, which then return it, but I don't know the correct way of returning.
I've been looking around tutorials and trying stuff out, but haven't managed to solve this.
I'm new to C++ and thought it would be similar to Java, but apparently it isn't.
This is where I've gotten:
class MainClass {
public:
static int countLetterCombinations(string array[], int numberOfWords) {
// Code
return totalCombos;
}
// This is the function I'm having trouble with.
static string** sortCombos(string combinations[][3]) {
// Do something
return combinations; // This gives converting error.
}
};
int main() {
// Code
int numberOfCombinations = MainClass::countLetterCombinations(words, numberOfWords);
string combinations[numberOfCombinations][3];
combinations = MainClass::sortCombos(combinations);
// Further code
}
Anyone know how to fix this?
You need to use a vector. C++ stack-based arrays cannot be dynamically sized- oh, and you can't convert [][] to **, the conversion only works for the first dimension. Oh, and you can't assign to arrays, either.
The simple rule is, in C++, never use primitive arrays- they're just a headache. They're inherited from C, which actually defined a lot of it's array behaviour for source compatibility with B, which is insanely old. Use classes that manage dynamic memory for you, like std::vector, for dynamically sizable arrays.
std::vector<std::array<std::string, 3>> combinations(numberOfCombinations);
static void sortCombos(std::vector<std::array<std::string, 3>>& combinations) {
// Do something
} // This function modifies combinations in-place and doesn't require a return.
Oh, and you really don't have to make functions static class members- they can just go in the global namespace.
Your sortCombos method can modify the array parameter in-place, and the caller will see those changes directly. Because you doesn't need to return anything, you should change the return type to void.
Even if you could return input array, you can't assign to combinations.
I am doing a project converting some Pascal (Delphi) code to C++ and would like to write a function that is roughly equivalent to the Pascal "SetLength" method. This takes a reference to a dynamic array, as well as a length and allocates the memory and returns the reference.
In C++ I was thinking of something along the lines of
void* setlength(void* pp, int array_size, int pointer_size, int target_size, ....) {
void * p;
// Code to allocate memory here via malloc/new
// something like: p = reinterpret_cast<typeid(pp)>(p);
// p=(target_size) malloc(array_size);
return p;
}
My question is this: is there a way to pass the pointer type to a function like this and to successfully allocate the memory (perhaps via a typeid parameter?)? Can I use
<reinterpret_cast>
somehow? The ultimate aim would be something like the following in terms of usage:
float*** p;
p=setlength(100,sizeof(float***),sizeof(float**),.....);
class B;
B** cp;
cp=setlength(100,sizeof(B**),sizeof(B*),.....);
Any help would be most welcome. I am aware my suggested code is all wrong, but wanted to convey the general idea. Thanks.
Use std::vector instead of raw arrays.
Then you can simply call its resize() member method.
And make the function a template to handle arbitrary types:
If you want to use your function, it could look something like this:
template <typename T>
std::vector<T>& setlength(std::vector<T>& v, int new_size) {
v.resize(new_size);
return v;
}
But now it's so simple you might want to eliminate the function entirely and just call resize to begin with.
I'm not entirely sure what you're trying to do with the triple-pointers in your example, but it looks like you don't want to resize though, you want to initialize to a certain size, which can be done with the vector constructor:
std::vector<float>v(100);
If you wanted to do it literally, you would do it like this:
template <typename T>
T* SetLength(T* arr, size_t len) {
return static_cast<T*>(realloc(arr, sizeof(T) * len));
}
Note that the array must have been allocated with malloc or calloc. Also note that this does not actually resize the memory—it deallocates the memory and reallocates memory of the appropriate size. If there were any other pointers to the array being passed in, they will be invalid afterwards.
You're really better off using a more idiomatic C++ solution, like std::vector.
For a multidimensional array, probably the best option would be to use boost's multi_array library:
typedef boost::multi_array<float, 3> array_type;
array_type p(boost::extents[100][100][100]); // make an 100x100x100 array of floats
p[1][2][3] = 4.2;
This lets you completely abstract away the allocation and details of setting up the multidimensional array. Plus, because it uses linear storage, you get the efficiency benefits of linear storage with the ease of access of indirections.
Failing that, you have three other major options.
The most C++-y option without using external libraries would be to use a STL container:
std::vector<float **> p;
p.resize(100);
As with multi_array, p will then automatically be freed when it goes out of scope. You can get the vector bounds with p.size(). However the vector will only handle one dimension for you, so you'll end up doing nested vectors (ick!).
You can also use new directly:
float ***p = new float**[100];
To deallocate:
delete [] p;
This has all the disadvantages of std::vector, plus it won't free it for you, and you can't get the size later.
The above three methods will all throw an exception of type std::bad_alloc if they fail to allocate enough memory.
Finally, for completeness, there's the C route, with calloc():
float ***p = (float ***)calloc(100, sizeof(*p));
To free:
free((void*)p);
This comes from C and is a bit uglier with all the casts. For C++ classes it will not call the constructors for you, either. Also, there's no checking that the sizeof in the argument is consistent with the cast.
If calloc() fails to allocate memory it will return NULL; you'll need to check for this and handle it.
To do this the C++ way:
1) As jalf stated, prefer std::vector if you can
2) Don't do void* p. Prefer instead to make your function a template of type T.
The new operator itself is essentially what you are asking for, with the exception that to appropriately allocate for double/triple pointers you must do something along the following lines:
float** data = new float*[size_of_dimension_1];
for ( size_t i=0 ; i<size_of_dimension_1 ; ++i )
data[i] = new float[size_of_dimension_2];
...
// to delete:
for ( size_t i=0 ; i<size_of_dimension_1 ; ++i )
delete [] data[i];
delete [] data;
Edit: I would suggest using one of the many C++ math/matrix libraries out there. I would suggest uBlas.