I am a total C++ noob, and I am having some trouble returning an array from my methods. I have a header file with the following method declaration:
virtual double[]
echoDoubleArray(double[] doubleArray, int arraySize) throw (RemoteException);
This gives me the following error:
../common/EchoService.h: At global scope:
../common/EchoService.h:25: error: expected unqualified-id before ‘[’ token
What is the correct way to return an array?
C++ doesn't play nice with non-local arrays, more likely you should be using an actual container like std::array<double,10> or std::vector<double>. I don't think it's possible to return an array from a function.
You'll better use std::vector or if you really want to return a plain array, return a pointer (to such an array) dynamically allocated with e.g.
double* arr = new double[arrSize];
// fill arr appropriately
return arr;
But I'll recommend returning a std::vector<double> instead.
Sorry everyone seems to be telling you to use modern STL type programming instead of answering your question. They are right. But you should still understand how things work. The problem with returning arrays are that arrays created in your function will be on the stack. When you leave your function they will not exist anymore. What you can do is return a pointer to an array on the Heap. Research a little more about the stack and the heap to understand. But below is a simple C++ function returning an array allocated on the Heap.
#include <iostream>
double * MakeArray()
{
double *mydouble = new double[5];
mydouble[1]=1.1;
mydouble[1]=2.2;
return mydouble;
}
int main()
{
double *d=MakeArray();
std::cout<<d[1]<<d[2];
delete[] d;
}
edit:
Thinking about it some more, another way to do it without STL would be returning a struct with an array in it. Most compilers will return a struct by value (assuming your not doing embedded programming).
Probably the best simple way: Pass your array into the function. It is like passing a reference because you are really just passing a pointer.
#include <iostream>
void MakeArray(double d[5])
{
d[0] = 0.0; d[1] = 1.1;
d[2] = 2.2; d[3] = 3.3; d[4] =4.4;
}
int main()
{
double dub[5];
MakeArray(dub);
std::cout<<dub[1]<<dub[2];
}
After understanding how everything works. go use the STL.
There is a technique for passing arrays that do not decay to pointers. You pass the array by reference, using the syntax below. The required "extra" parens are a syntactical wart, and probably why this usage is not more common. One gets used to it real fast, given the advantages.
void sub(double (&foo)[4])
{
cout << sizeof(foo) << endl;
}
Prints 32, not sizeof(double*), because the type of foo really is a reference to an array of 4 doubles. Using templates, you can generalize to work for any size of array:
template <int N> sub(double (&foo)[N])
{
cout << sizeof(foo) << endl;
}
double bar[5];
double zot[3];
sub(bar); // ==> 40
sub(zot); // ==> 24
You can generalize again to handle an any-size array of anything:
template <class T, int N>void sub(T(&foo)[N])
{
cout << sizeof(foo) << endl;
}
double bar[5];
char zot[3];
sub(bar); // ==> 40
sub(zot); // ==> 3
and you now have something that captures the abstract idea of "sub" regardless of the type or size of the array you pass it.
The C++ syntax for arrays is: std::vector<double> instead of double[]. It also requires you to put #include <vector> near the top of your source file. Other than that they work very similar to C-arrays.
To answer your question more directly, if you declare an array of doubles as follows:
double doubleArray[] = {1.0, 2.0, 3.0};
you would declare the method like this:
virtual double *
echoDoubleArray(double* doubleArray, int arraySize) throw (RemoteException);
Arrays are passed as pointers. If you want to use the true power of C++, then follow the advice provided in the other answers.
Related
I am trying to make a void function where it changes the pointer that I pass. The code is throwing an exception on one of the lines and i'm not sure why. Could it be I cannot pass the arrays as pointers then implement math on it? I thought I deallocated the pointers to fix it but this seemed to not work.
Void function:
#include <iostream>
using namespace std;
void* func2(int one, double *value1[], int two, double *value2[], double *final1) {
double testval;
double finalval = 0;
//double *final1;
double final = 0;
for (int i = 1; i < one; i++) {
for (int j = 1; j < two; j++) {
testval = *value1[i] * *value2[j]; //exception thrown (works up to this point)
finalval = testval + finalval;
}
final = finalval + final;
}
*final1 = final;
return 0;
}
Main Function:
int main(){
double *array1 = new double[input1];
double *array2 = new double[input2];
//for loop that takes user input and fills in array1 and array2 with size and a list of values
...
double testval2;
func2(input1, &array1, input2, &array2, &testval2);
cout << testval2 << endl;
delete[] array1;
delete[] array2;
return 0;
I am relatively new to pointers, so my apologies if the code is a little illiterate.
It looks like you want to pass two 1D arrays to func2().
One way to do that is remove the [] from the function signature as
(int one, double *value1, int two, double *value2, double *final1)
Within the function, change *value1[i] to value1[i], and similarly for value2. And remove the & when calling the function from the main().
A couple other thoughts:
I'm not sure how an exception could throw from your code. But *value1[i] is definitely an invalid memory access, so what you may have seen is a segmentation fault message. A helpful tool to troubleshoot these kinds of errors is AddressSanitizer, enabled in clang or gcc by compiling with -fsanitize=address, or if you are using Xcode, there is an option for it. Another great tool is valgrind.
Manually allocating dynamic arrays is a pretty C-like way of using C++. In C++, it is idiomatic to create the arrays as std::vector objects, which under the hood works the same way (it also allocates a dynamic array) but has a more convenient interface. Particularly the vector cleans itself up automatically, so no need to call delete[], and the vector knows its own size, so no need to pass the size around as a separate parameter as with dynamic arrays.
Edit: Here is a note to clarify why the original code manages to compile but fails at runtime.
In the function signature, the combo of both * and [] on double *value1[] makes value1 a pointer to a pointer to double, equivalent to double **value1. In main(), array1 is a double*. When calling the function, &array1 takes the address of that double*, obtaining a double**. So the type matches and the code compiles.
The code fails at runtime on *value1[i]. value1 is a pointer to pointer to doubles, where the inner pointer points to the dynamic array. So what was intended is (*value1)[i] to first dereference the outer pointer, then subscript into the dynamic array. However, in C++, subscripting (a[]) has operator precedence over dereferencing (*a), so it is read in backward order as *(value1[i]). Subscripting the outer pointer value1[i] is invalid for nonzero i, reading memory from somewhere in the stack and arbitrarily interpreting it as a double*. Then the surrounding *( ) attempts to dereference this busted pointer. The machine's memory protection catches this, and the OS sends a "SIGSEGV" signal or similar to the program to kill it.
Say I have the following code:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int * arg = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
and the result is:
2
3
which make sense because the pointer *arg manipulated the array defaultvalue. However, if I changed the code into:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int arg[] = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
but the result is still:
2
3
Moreover, when I print out the defaultvalue:
cout << defaultvalue[0] <<endl;
It turn out to be 3.
My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue?
My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue?
No.
It is impossible to pass an array by value (thanks a lot, C!) so, as a "compromise" (read: design failure), int[] in a function parameter list actually means int*. So your two programs are identical. Even writing int[5] or int[24] or int[999] would actually mean int*. Ridiculous, isn't it?!
In C++ we prefer to use std::array for arrays: it's an array wrapper class, which has proper object semantics, including being copyable. You can pass those into a function by value just fine.
Indeed, std::array was primarily introduced for the very purpose of making these silly and surprising native array semantics obsolete.
When we declare a function like this
int func(int* arg);
or this
int (func(int arg[])
They're technically the same. It's a matter of expressiveness. In the first case, it's suggested by the API author that the function should receive a pointer to a single value; whereas in the second case, it suggests that it wants an array (of some unspecified length, possibly ending in nullptr, for instance).
You could've also written
int (func(int arg[3])
which would again be technically identical, only it would hint to the API user that they're supposed to pass in an int array of at least 3 elements. The compiler doesn't enforce any of these added modifiers in these cases.
If you wanted to copy the array into the function (in a non-hacked way), you would first create a copy of it in the calling code, and then pass that one onwards. Or, as a better alternative, use std::array (as suggested by #LightnessRacesinOrbit).
As others have explained, when you put
int arg[] as a function parameter, whatever is inside those brackets doesn't really matter (you could even do int arg[5234234] and it would still work] since it won't change the fact that it's still just a plain int * pointer.
If you really want to make sure a function takes an array[] , its best to pass it like
template<size_t size>
void func (const int (&in_arr)[size])
{
int modifyme_arr[100];
memcpy(modifyme_arr, in_arr, size);
//now you can work on your local copied array
}
int arr[100];
func(arr);
or if you want 100 elements exactly
void func (const int (&arr)[100])
{
}
func(arr);
These are the proper ways to pass a simple array, because it will give you the guaranty that what you are getting is an array, and not just a random int * pointer, which the function doesn't know the size of. Of course you can pass a "count" value, but what if you make a mistake and it's not the right one? then you get buffer overflow.
I have an Eigen matrix to be converted to a C array. I can replicate the issue with the following example.
#include <iostream>
#include <Eigen/Core>
int *test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
// just to check
arr(4)=3;
arr(5)=19;
return arr.data();
}
int main()
{
int *c_arr;
c_arr = test();
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
Output:
0
0
1
1
3
19
Now if I print the converted C array values from within the test function the values are correct. However if I print the values from main (as shown above) the first two indices are always garbage. So I am wondering what is happening in the function call? I have tried this with different Eigen matrices (types, sizes) and I get the same result.
I'll start by saying I'm not 100% familiar with the Eigen library (just downloaded it to look at it out of curiosity) and it's documentation is a bit lacking but your problem is a fundamental C problem that can be remedied a few ways.
First we'll start by explaining what's happening in your code to give garbage values:
int *test()
{
/* create an auto scoped variable on the stack;
this variable is only "visible" to this function
and any references to it or it's underlying data
outside the scope of this function will result
in "undefined behaviour" */
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
/* arr.data() is defined as returning a pointer to the scalar underlying type (or
a C-style array in other words). Regardless of the type being returned, it is pointer based
and you are returning a pointer to a location in memory, not the actual data being held in
the memory. */
return arr.data();
} /* the variable arr is destroyed here since we left function scope and the return value (the pointer location)
is put in the return register and "program flow" is returned back to the main function where the pointer being
returned now points to "invalid" memory */
int main()
{
int *c_arr; // create a pointer type that can reference int types
c_arr = test(); // point it to the result of the test function (see notes above)
/* c_arr now points to a memory location returned from test, but since the
arr variable no longer exists here, when you go through and print the values pointed
to at those memory locations you will get what is at those locations and could be "anything"
except a valid reference to the original arr variable and it's underlying data. */
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
So that's the why, as for how to fix it there are a couple of ways to go about your problem; one is to pass the return array in as a variable in to your test function (e.g. void test(int*& val)), you could then choose to allocate new memory to the variable in the test function, or assume the user has already done so, and must also assume the user will clean up after themselves and call delete[] (not just delete since you're operating on arrays of data).
But this has many caveats of needing to know how much space to allocate and being sure to deallocate when done. I'm not sure why you specifically need a C-style array but since you're using C++, it might be more prudent if you use some of the STL and container functions available to you to help you out, example:
#include <iostream>
#include <vector>
#include <Eigen/Core>
std::vector<int> test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
// we need the size so we know how big of a container to allocate
std::size_t sz = arr.innerSize() * arr.outerSize();
std::vector<int> ret(sz);
// get a temporary C array pointer so we can reference the data
int* tmp = arr.data();
// copy from tmp[0] to tmp[sz] and insert the data into the first element of ret
std::copy(tmp, tmp+sz, ret.begin());
// return the (copied) data
return ret;
}
int main()
{
std::vector<int> c_arr = test();
// c_arr now points to valid data it holds and can be iterated on
for (std::size_t i = 0; i < c_arr.size(); ++i) {
std::cout << c_arr[i] << std::endl;
}
// if you need a C-style array from here, you can easily copy the data
// from the vector to your C-array
return 0;
}
I looked into using the cast() function of the class, but could not quite figure out the syntax to make it less painful than just copying it the above way since it looks like you'd have to call the cast function to a differnt Eigen type and then cast again from there, but know there is a cast function and other methods to get the underlying data of the MatrixX classes if you need access to it.
I hope that can help.
I am trying to return an array from a function:
#include <iostream>
using namespace std;
int* uni(int *a,int *b)
{
int c[10];
int i=0;
while(a[i]!=-1)
{
c[i]=a[i];
i++;
}
for(;i<10;i++)
c[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
int *c=uni(a,b);
for(int i=0;i<10;i++)
cout<<c[i]<<" ";
cout<<"\n";
return 0;
}
I pass two arrays from my main() into my uni() function. There I create a new array c[10] which I return to my main().
In my uni() function I try to merge the non-negative numbers in the two arrays a and b.
But I get something like this as my output.
1 -1078199700 134514080 -1078199656 -1216637148 134519488 134519297 134519488 8 -1078199700
Whereas when I try to print the values of c[10] in the uni() function it prints the correct values. Why does this happen??
Is this something related to the stack?? Because I have tried searching about this error of mine, and I found a few places on stackoverflow, where it says that do not allocate on stack but I couldn't understand it.
Further it would become very easy if I allocate my array globally, but if this is the case then everything shall be declared globally?? Why are we even worried about passing pointers from functions?? (I have a chapter in my book for passing pointers)
Admittedly, the std::vector or std::array approach would be the way to go.
However, just to round things out (and if this is a school project, where the teacher gives you the obligatory "you can't use STL"), the other alternative that will avoid pointer usage is to wrap the array inside a struct and return the instance of the struct.
#include <iostream>
using namespace std;
struct myArray
{
int array[10];
};
myArray uni(int *a,int *b)
{
myArray c;
int i=0;
while(a[i]!=-1)
{
c.array[i]=a[i];
i++;
}
for(;i<10;i++)
c.array[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
myArray c = uni(a,b);
for(int i=0;i<10;i++)
cout << c.array[i] << " ";
cout << "\n";
return 0;
}
Note that the struct is returned by value, and this return value is assigned in main.
You have the value semantics of returning an instance, plus the struct will get copied, including the array that is internal within it.
Live Example
You're returning a pointer to a local object. In the uni function, the variable c is allocated on the stack. At the end of that function, all of that memory is released and in your for loop you are getting undefined results.
As suggested in the comments, std::array or std::vector will give you copy constructors that will allow you to return the object by value as you're trying to do. Otherwise you'll have to resort to something like passing your output array in as an argument.
You are returning a pointer to an array that is being deallocated at the return statement. It's a dangling pointer. It's UB.
Use an std::vector or std::array and return by value. There are compiler optimizations that will avoid inefficiencies.
I am a bit confused. There are two ways to return an array from a method. The first suggests the following:
typedef int arrT[10];
arrT *func(int i);
However, how do I capture the return which is an int (*)[]?
Another way is through a reference or pointer:
int (*func(int i)[10];
or
int (&func(int i)[10];
The return types are either int (*)[] or int (&)[].
The trouble I am having is how I can assign a variable to accept the point and I continue to get errors such as:
can't convert int* to int (*)[]
Any idea what I am doing wrong or what is lacking in my knowledge?
If you want to return an array by value, put it in a structure.
The Standard committee already did that, and thus you can use std::array<int,10>.
std::array<int,10> func(int i);
std::array<int,10> x = func(77);
This makes it very straightforward to return by reference also:
std::array<int,10>& func2(int i);
std::array<int,10>& y = func2(5);
First, the information you give is incorrect.
You write,
“There are two ways to return an array from a method”
and then you give as examples of the ways
typedef int arrT[10];
arrT *func(int i);
and
int (*func(int i))[10];
(I’ve added the missing right parenthesis), where you say that this latter way, in contrast to the first, is an example of
“through a reference or pointer”
Well, these two declarations mean exactly the same, to wit:
typedef int A[10];
A* fp1( int i ) { return 0; }
int (*fp2( int i ))[10] { return 0; }
int main()
{
int (*p1)[10] = fp1( 100 );
int (*p2)[10] = fp2( 200 );
}
In both cases a pointer to the array is returned, and this pointer is typed as "pointer to array". Dereferencing that pointer yields the array itself, which decays to a pointer to itself again, but now typed as "pointer to item". It’s a pointer to the first item of the array. At the machine code level these two pointers are, in practice, exactly the same. Coming from a Pascal background that confused me for a long time, but the upshot is, since it’s generally impractical to carry the array size along in the type (which precludes dealing with arrays of different runtime sizes), most array handling code deals with the pointer-to-first-item instead of the pointer-to-the-whole-array.
I.e., normally such a low level C language like function would be declared as just
int* func()
return a pointer to the first item of an array of size established at run time.
Now, if you want to return an array by value then you have two choices:
Returning a fixed size array by value: put it in a struct.
The standard already provides a templated class that does this, std::array.
Returning a variable size array by value: use a class that deals with copying.
The standard already provides a templated class that does this, std::vector.
For example,
#include <vector>
using namespace std;
vector<int> foo() { return vector<int>( 10 ); }
int main()
{
vector<int> const v = foo();
// ...
}
This is the most general. Using std::array is more of an optimization for special cases. As a beginner, keep in mind Donald Knuth’s advice: “Premature optimization is the root of all evil.” I.e., just use std::vector unless there is a really really good reason to use std::array.
using arrT10 = int[10]; // Or you can use typedef if you want
arrT10 * func(int i)
{
arrT10 a10;
return &a10;
// int a[10];
// return a; // ERROR: can't convert int* to int (*)[]
}
This will give you a warning because func returns an address of a local variable so we should NEVER code like this but I'm sure this code can help you.