General rules of passing/returning reference of array (not pointer) to/from a function?
If you want to return a reference to an array from a function, the declaration would look like this:
// an array
int global[10];
// function returning a reference to an array
int (&f())[10] {
return global;
}
The declaration of a function returning a reference to an array looks the same as the declaration of a variable that is a reference to an array - only that the function name is followed by ()
, which may contain parameter declarations:
int (&variable)[1][2];
int (&functionA())[1][2];
int (&functionB(int param))[1][2];
Such declarations can be made much clearer by using a typedef:
typedef int array_t[10];
array_t& f() {
return global;
}
If you want it to get really confusing, you can declare a function that takes a reference to an array and also returns such a reference:
template<int N, int M>
int (&f(int (¶m)[M][N]))[M][N] {
return param;
}
Pointers to arrays work the same, only that they use *
instead of &
.
C: When to return by value or pass reference
Start by deciding which approach makes the most sense at the logical level, irrespective of what you think the performance implications might be. If returning a struct
by value most clearly conveys the intent of the code, then do that.
This isn't the 1980s anymore. Compilers have gotten a lot smarter since then and do a really good job of optimizing code, especially code that's written in a clear, straightforward manner. Similarly, parameter passing and value return conventions have become fairly sophisticated as well. The simplistic stack-based model doesn't really reflect the reality of modern hardware.
If the resulting application doesn't meet your performance criteria, then run it through a profiler to find the bottlenecks. If it turns out that returning that struct
by value is causing a problem, then you can experiment with passing by reference to the function.
Unless you're working in a highly constrained, embedded environment, you really don't have to count every byte and CPU cycle. You don't want to be needlessly wasteful, but by that same token you don't want to obsess over how things work at the low level unless a) you have really strict performance requirements and b) you are intimately familiar with the details of your particular platform (meaning that you not only know your platform's function calling conventions inside and out, you know how your compiler uses those conventions as well). Otherwise, you're just guessing. Let the compiler do the hard work for you. That's what it's there for.
How to return a reference to an array of ten strings
You can pass the array by reference, so you can return it :
std::string (&func(std::string (& a) [10])) [10]
{
return a;
}
Or to make things clearer, use a typedef
for your array of strings:
typedef std::string StrArray[10];
StrArray& func2(StrArray& a) {
return a;
}
EDIT:
When you did :
std::string (&func(std::string a[])) [10]
{
return a; // error !
}
The argument a
is an array of std::string
and decays to a pointer to std::string*
, which is passed by value (so, copied): You are asking the compiler to bind a non-const reference (the return type) to a temporary, which is illegal in C++.
C++ function returning reference to array
Is there any other way to receive a reference to an array from function returning except using a pointer?
Yes, using a reference to an array, like with any other type:
int (&ref)[3] = a.foo();
To avoid the clunky syntax, you could use a typedef
instead.
typedef int int_array3[3];
...
int_array3& foo() { return ia; }
...
int_array3& ref = a.foo();
Are arrays passed by value or passed by reference in Java?
Your question is based on a false premise.
Arrays are not a primitive type in Java, but they are not objects either ... "
In fact, all arrays in Java are objects1. Every Java array type has java.lang.Object
as its supertype, and inherits the implementation of all methods in the Object
API.
... so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?
Short answers: 1) pass by value, and 2) it makes no difference.
Longer answer:
Like all Java objects, arrays are passed by value ... but the value is the reference to the array. So, when you assign something to a cell of the array in the called method, you will be assigning to the same array object that the caller sees.
This is NOT pass-by-reference. Real pass-by-reference involves passing the address of a variable. With real pass-by-reference, the called method can assign to its local variable, and this causes the variable in the caller to be updated.
But not in Java. In Java, the called method can update the contents of the array, and it can update its copy of the array reference, but it can't update the variable in the caller that holds the caller's array reference. Hence ... what Java is providing is NOT pass-by-reference.
Here are some links that explain the difference between pass-by-reference and pass-by-value. If you don't understand my explanations above, or if you feel inclined to disagree with the terminology, you should read them.
- http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
- http://www.cs.fsu.edu/~myers/c++/notes/references.html
Related SO question:
- Is Java "pass-by-reference" or "pass-by-value"?
Historical background:
The phrase "pass-by-reference" was originally "call-by-reference", and it was used to distinguish the argument passing semantics of FORTRAN (call-by-reference) from those of ALGOL-60 (call-by-value and call-by-name).
In call-by-value, the argument expression is evaluated to a value, and that value is copied to the called method.
In call-by-reference, the argument expression is partially evaluated to an "lvalue" (i.e. the address of a variable or array element) that is passed to the calling method. The calling method can then directly read and update the variable / element.
In call-by-name, the actual argument expression is passed to the calling method (!!) which can evaluate it multiple times (!!!). This was complicated to implement, and could be used (abused) to write code that was very difficult to understand. Call-by-name was only ever used in Algol-60 (thankfully!).
UPDATE
Actually, Algol-60's call-by-name is similar to passing lambda expressions as parameters. The wrinkle is that these not-exactly-lambda-expressions (they were referred to as "thunks" at the implementation level) can indirectly modify the state of variables that are in scope in the calling procedure / function. That is part of what made them so hard to understand. (See the Wikipedia page on Jensen's Device for example.)
1. Nothing in the linked Q&A (Arrays in Java and how they are stored in memory) either states or implies that arrays are not objects.
Class accept and return array
First of all it is better to write the constructor either like
myclass ( const int ( &temp )[10] ) {
for (size_t i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
or like
myclass ( int temp[], size_t n ) : Array {} {
if ( n > 10 ) n = 10;
for (size_t i = 0; i < n; i++) {
Array [i] = temp [i];
}
}
Or even you may define the both constructors.
As for the returning value then you may not return an array. You may return either a reference to an array or a pointer to the entire array or a pointer to its first element
For example
int ( &returnArray () )[10] {
return Array;
}
In this case you can write in main
for ( int x : A.returnArray() ) std::cout << x << ' ';
std::cout << std::endl;
As for this statement
cout << *ptr->returnArray2 << endl; // error here
then you forgot to place parentheses after returnArray2. Write
cout << *ptr->returnArray2() << endl;
And the following member function is wrong because the expression in the return statement has type int *
while the return type of the function is int
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
So either the function will coincide with the the second member function if you specify its return type like int *
. Or you could change the return expression to *Array
Related Topics
Private Inheritance VS Composition:When to Use Which
How-To Write a Password-Safe Class
Unique_Ptr and Forward Declaration
Can Sfinae Detect Private Access Violations
Cmake Cannot Determine Linker Language for Target
Math Precision Requirements of C and C++ Standard
How to Overwrite Only Part of a File in C++
Why How to Call Base Template Class Method from Derived Class
When Do We Need to Pass the Size of Array as a Parameter
Write a Recursive Function That Reverses the Input String
How to Handle Key Press Events in C++
How to Implement Timeout for Function in C++
How to Generate Random Numbers in C++
How to Enable Experimental C++11 Concurrency Features in Mingw
Differencebetween C-Like Casting and Functional Casting
What the Heque Is Going on with the Memory Overhead of Std::Deque