This question already has answers here:
Return array in a function
(20 answers)
Closed 10 years ago.
Here is my code
double hour_payload_add(int entries , double array[])
{
int index=0 ,k=0;
int totalpayload=0;
double returnarray[entries/120];
while(k< entries)
{
totalpayload = totalpayload + array[k];
if(k%120==0)
{
returnarray[index] = totalpayload;
index++;
totalpayload=0;
}
}
return returnarray;
}
here I have called it
double hourgraph[hrentries];
hourgraph= hour_payload_add(entries , graph);
as I want to return an array what should I do to return without using pointers?
Pass the array by reference to the function and don't return anything. Small example:
void hour_payload_add(int entries , double array[], double (&returnArray)[SIZE])
{
// returnArray will be updated as it's external to function.
}
or
void hour_payload_add(int entries , double array[], double *returnArray) // <-- pointer
{
// returnArray will be updated as it's external to function.
}
usage:
double returnArray[SIZE];
hour_payload_add(entries, array, returnArray);
Two lines changed:
std::vector<double> hour_payload_add(int entries , std::vector<double> array) // HERE
{
int index=0 ,k=0;
int totalpayload=0;
std::vector<double> returnarray(entries/120); // HERE
/// ....
return returnarray;
}
Okay, maybe add one at the top
#include <vector>
For full bonus, I suggest changing it a bit more:
std::vector<double> hourgraph(hrentries);
hourgraph = hour_payload_add(graph);
// ...
std::vector<double> hour_payload_add(std::vector<double> array)
{
const size_t entries = array.size();
For that you should be using a pointer and create the array before you fill it (not in the function that is filling it).
double* hour_payload_add(int entries , double array[])
However I prefer to pass arrays as a reference.
void hour_payload_add(int entries , double array[], double& ret_array[])
Or even better (as others will say) would be to use vectors.
void hour_payload_add(std::vector<double>array, std::vector<double>& ret_array)
You have to create your array using new. So your function should be like this:
double* hour_payload_add(int entries , double array[])
{
int index=0 ,k=0;
int totalpayload=0;
double* returnarray = new double[entries/120];
while(k< entries)
{
totalpayload = totalpayload + array[k];
if(k%120==0)
{
returnarray[index] = totalpayload;
index++;
totalpayload=0;
}
}
return returnarray;
}
After using the array you must free the space by calling delete[] on the array to avoid memory leaks:
int entries = 5;
double* array = hour_payload_add(entries);
for (int i=0; i < entries; i++)
{
std::cout << array[i] << std::endl;
}
delete[] array;
You cannot return arrays in C++ - you would rather return a pointer to a piece of memory.
Moreover, you cannot return a pointer to a locally declared array that is on the stack because the stack is restored right after the function terminates. You have to allocate it dynamically with new or malloc, and return a pointer to its beginning.
In general you should not use arrays in C++, instead preferring the use of the STL Container Classes (std::vector is the most array-like of these). Of course there are exceptions, and in some cases you should use an array (never say never), but in your example I would suggest the use of vector instead.
Sehe's answer provides an example of using the std::vector, and initialising it with the size of the array:
std::vector<double> returnarray(entries/120);
This uses a constructor that sets the default size of the array. More usefully a vector can change size dynamically, and you can, as suggested, return it from a function. Depending on the optimisation done by the compiler, it may not even create a copy of the vector - but this is compiler-dependent.
My suggestion is to look at documentation on vector and other containers in preference to an array.
You cannot return an c style Array from a function in C++. But Yes you can return a std::array container from a function
You can return starting address of the c style array which is created locally on inside the function but that array gets cleared off when function returns and you are left with a pointer pointing to not what you wanted.
You will have to dynamically allocate a array using new and then return pointer to it.
Related
If I have a C type raw pointer, is it possible to create a std::vector from the same type that owns the pointer's data without any data copy (only moving)? What motivates me for asking this question is the existence of data() member function for std::vector which means vector's elements are residing somewhere in the memory consecutively.
Edit: I have to add that the hope I had was also intensified by the existence of functions like std::make_shared.
I don't think that this is directly possible, although you're not the first one to miss this feature. It is even more painful with std::string which doesn't have a non-const data member. Hopefully, this will change in C++17.
If you are allocating the buffer yourself, there is a solution, though. Just use a std::vector up-front. For example, assume you have the following C-style function,
extern void
fill_in_the_numbers(double * buffer, std::size_t count);
then you can do the following.
std::vector<double>
get_the_numbers_1st(const std::size_t n)
{
auto numbers = std::vector<double> (n);
fill_in_the_numbers(numbers.data(), numbers.size());
return numbers;
}
Alternatively, if you're not so lucky and your C-style function insists in allocating the memory itself,
extern double *
allocate_the_buffer_and_fill_in_the_numbers(std::size_t n);
you could resort to a std::unique_ptr, which is sadly inferior.
std::unique_ptr<double[], void (*)(void *)>
get_the_numbers_2nd(const std::size_t n)
{
return {
allocate_the_buffer_and_fill_in_the_numbers(n),
&std::free
};
}
No, std::vector is not designed to be able to assume/utilize a pre-existing array for its internal storage.
Yes, provided that you've created and populated the vector before getting the pointers and that you will not
erase any element
you will not add new elements when vec.size() == vec.capacity() - 1 ,,, doing so will change the address of the elements
Example
#include <iostream>
void fill_my_vector<std::vector<double>& vec){
for(int i=0; i<300; i++){
vec.push_back(i);
}
}
void do_something(double* d, int size)
{ /* ..... */ }
int main(){
std::vector<double> vec;
fill_my_vector(vec);
//You hereby promise to follow the contract conditions, then you are safe doing this
double* ptr;
int ptr_len = vec.size();
ptr = &vec[0];
//call do_something
do_something(ptr, ptr_len);
//ptr will be alive until this function scope exits
}
EDIT
If you mean managing the data from an already created array, you can't... vector manages its own array... It cannot take ownership of an array that wasn't created by its class (vector).
This question already has answers here:
Is 2d array a double pointer? [duplicate]
(4 answers)
Closed 7 years ago.
I'm solving an algorithm problem using C++.
I want to put the pointer of 2-dimensional array that having different sizes of each dimension by init input dynamically.
What I coded as a function is below: the contents(the function of function) mean nothing.
int cal(int **arr){
int test = arr[0][0];
return 0;
}
And the result of this function
int arrayD[totalGroupCount][totalBeadCount];
int a = cal(arrayD);
It just says "No Matching function call for 'cal'"
I did declare the function 'cal'.
And I did it a lot with different symbol
int cal(int *arr[]){
int test = arr[0][0];
return 0;
}
But it says me identically.
I already searched for this question but answers I got make just the same error(I totally don't understand how they make it)
As you use c++, there's better solution with std::vector< vector<int > >
int cal(std::vector<std::vector<int> > arr)
{
int test = arr[0][0];
return 0;
}
And call the function
std::vector<std::vector<int> >arrayD (totalGroupCount, std::vector<int>(totalBeadCount));
int a = cal(arrayD);
Also you can use push_back() function to dynamically add element to the vector.
You need to allocate memory with malloc, calloc, or new:
long a;
int **pt; // a pointer to pointer to int
pt=new int*[rows]; // allocate memory for pointers,
// not for ints
for (a=0;a<rows;++a) pt[a]=new int[columns]; // here you're allocating
// memory for the actual data
This will create an array similar to pt[rows][columns].
Then you pass pt like this:
int Func(int **data) {
//do something
return //something
}
Func(pt);
I'm trying to return a pointer to an array from a function but I have an issue. When I try to output like this:
#include <iostream>
using namespace std;
int* Somma_Array(int[],int[],int);
int main()
{
int n;
cin>>n;
int A[n],B[n];
for(int i=0;i<n;i++)cin>>A[i];
for(int i=0;i<n;i++)cin>>B[i];
int *c=Somma_Array(A,B,n);
for(int i=0;i<n*2;i++)cout<<c[i];
}
int* Somma_Array(int v[],int p[],int size)
{
int r[size*2];
for(int i=0;i<size;i++)r[i]=v[i];
for(int i=0;i<size;i++)r[i+size]=p[i];
return r;
}
it prints weird numbers instead of the actual number. I tried to do what this question says but it does not work. It gives me the following warning:
[Warning] address of local variable 'r' returned [enabled by default]
I'm using bloodshed dev-c++.
You define a stack allocated array r, which is destroyed when you exit the function Soma_Array. This is one of the (many) reasons vectors are preferred to plain arrays - they handle allocation and deallocation for you.
#include <vector>
std::vector<int> getArray()
{
std::vector<int> a = {1, 2, 3};
return a;
}
The following:
int r[size*2];
defines r locally. When the function exits (as in the scope of the function expires), r will be destroyed since it is bound to the function's scope. You are likely seeing junk data from the stack frame.
you could fix this by doing the following:
int* r = new int[size * 2];
The variable r will now be heap allocated and exist beyond the scope of the function.
IMPORTANT by doing this, you now must manually free r when you are done with it. So for instance, your calling code will look something like this:
int* result = Somma_Array(v, p, size);
/* ... do stuff ... */
delete[] result;
Since r is an array, note the use of delete[] instead of delete. delete[] is the correct way to destroy arrays.
A Better Alternative
Would std::vector be more what you are after? This is a much safer alternative to hand-rolled arrays. The vector is safer to use, scales automatically as you add elements, and cleans itself up nicely when it leaves scope (assuming you are using a value-type instance). Additionally, vectors can be copied and moved out of functions easily.
You cannot return arrays in C++. Especially, you should not return a pointer to a local array. You can however return a std::vector<int>:
std::vector<int> Somma_Array(int v[], int p[], int size)
{
std::vector<int> r(2 * size);
std::copy(v, v + size, r.begin());
std::copy(p, p + size, r.begin() + size);
return r;
}
I'm brand new to C++ and am having trouble trying to get a function (which takes an array) to return an array. The function is a very basic sorting algorithm for an array of integers of size 4. What i have is below:
int[] sortArrayAscending(int arrayToSort[3]) {
int sortedArray[3];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
I think i'm getting really confused with the syntax i need to use (the function calls to min, lower, higher, max all work fine.
I would really appreciate some help.
Thank you
EDIT2: Thank you for all the comments. I have now solved it thanks to #Rook's and #Bob Yoplait's answers. The code is used is:
int* sortArrayAscending(int arrayToSort[4], int sortedArray[4]) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
int _tmain(int argc, _TCHAR* argv[])
{
int testNumbers[4] = {8,14,1,27};
int testSorted[4];
sortArrayAscending(testNumbers,testSorted);
for (int i = 0; i < 4; i++) {
cout << testSorted[i] << endl;
}
system("pause");
return 0;
}
Thank you for all your help - now time to lookup vectors!
PS I appreciate #Luchian Grigore's solution is most likely the best practise way of doing things, but that wasn't specifically my question
Me, I'd probably use std::array<int, 4> if I was using a modern C++ compiler. Deals nicely with bounds checking and memory management and returning from/passing into functions. You can also use existing STL sort mechanisms and functions upon it; no need to reinvent the wheel!
Now, in your case,
int sortedArray[3];
is a local variable and you should never return a reference to it directly. You could do something like :
int* sortedArray = new int[4];
// do stuff
return sortedArray;
(also note the size of the array, 4, not 3 in your case!) but in this case you have to remember to delete the array at some point in the future or your application will leak memory.
You can also pass in the array by reference, using an approach like
void sort_array(std::array<int, 4>& the_array);
or
void sort_array(int** the_array)
and in these cases you can modify the array in place, or copy the answer into the argument when you're done sorting.
EDIT: After your edit, you, your function returns a pointer to an array. Should work.
You can either return a pointer or a std::vector.
Note that in your code, you'd be running into undefined behavior, because sortedArray goes out of scope at the end of the method, and the memory is freed.
I'd do this instead:
std::vector<int> sortArrayAscending(int arrayToSort[4]) {
std::vector<int> sortedArray(4);
sortedArray.push_back( minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
return sortedArray;
}
Actually, I wouldn't. I'd just use std::sort instead of creating my own function, but that's just me.
As this is C++, suggest using a std::vector<int> instead:
std::vector<int> sortArrayAscending(int arrayToSort[3]) {
std::vector<int> sortedArray(4); // Note 4, not 3.
sortedArray[0] = ...;
sortedArray[1] = ...;
sortedArray[2] = ...;
sortedArray[3] = ...;
return sortedArray;
}
Note there are several algorithms already available that will perform some of the tasks that you appear to be performing:
max_element()
min_element()
You are returning pointer to local variable, which leads to undefined behavior. sortedArray is statically allocated array with automatic storage duration, which means that memory where it resides is being freed once you leave the scope of the function.
You should allocate it dynamically by using new[] or even better: use std::vector instead. If you choose to allocate it by using new[], don't forget to free it by calling delete[] when you don't need this memory anymore.
Also note that int sortedArray[3]; declares an array of size of 3 elements indexed from 0 to 2. If you access 4th element of the array whose size is 3 (if you access the memory "past the last element of the array object"), the behavior is undefined as well.
Use Boost::Array (or std::array in C+11) that provides proper value semantic to C array.
boost::array<int,4> sortArrayAscending(boost::array<int,4>7 arrayToSort)
{
boost::array<int,4> sortedArray;
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
It is not like in Java
Either you pass sortedArray as a parameter to the func
int* sortArrayAscending(int* arrayToSort, int* sortedArray) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
void toto() {
int array[4]; // and fill values...
int sortedArray[4];
sortArrayAscending(array, sortedArray);
}
or
int* sortArrayAscending(int* arrayToSort) {
int* sortedArray = new int[4];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
and then you need to delete the returned array in the second case.
Arrays are always passed by reference to any function in C++.
So, just pass your array to the function. Your original array would get sorted and you can then use it in your program. I believe there is no need to return the array explicitly.
I have got a small problem with 1D array in c++. I have got a function line this:
void func(int (&array)[???])
{
// some math here;
"for" loop {
array[i] = something;
}
}
I call the functions somewhere in the code, and before I made math I'm not able to know dimension of the array. The array goes to the function as a reference!, because I need it in the main() function. How I can allocate array like this?, so array with ?? dimension goes to the function as reference then I have to put the dimension and write to it some values.
Since you're using C++, why not use a std::vector<> instead?
Other have mentioned that you should use std::vector in C++ and they are right.
But you can make your code work by making func a function template.
template <typename T, size_t N>
void func(T (&array)[N])
{
// some math here;
"for" loop {
array[i] = something;
}
}
Use a pointer, not a reference:
void func(int *a, int N);
Or, easier, use a vector:
void func(std::vector<int> &a);
Vectors can be allocated by simply saying
std::vector<int> a(10);
The number of elements can be retrieved using a.size().
If the array you pass to func is a stack array, and not a pointer, you can retain its size by using a function template:
template <class T, size_t N>
void func(T(&array)[N])
{
size_t array_length = N; // or just use N directly
}
int main()
{
int array[4];
func(array);
}
That said, as others have already pointed out, std::vector is probably the best solution here.
As well as vector which has been suggested you could possibly use valarray which is also part of STL and is intended specificially to handle mathematical collections.
What you have to realize, is that arrays are pointers. A definition like int array[5] will allocate space for 5 integers on the stack and array will be the address of the first value. Thus, to access the first value in the array, you can write
array[0] or *array (which is the same as *(array + 0))
In the same way to retrieve the address of the third element, you can write
&array[2] or array + 2
Since arrays are pointers, you don't have to worry about the runtime size of your array if you would like to pass it to a function, simply pass it as a pointer:
void func(int *array)
{
int size;
//compute size of the array
for (int i = 0; i < size; ++i)
{
//do whatever you want with array[i]
}
}