Regarding two dimensional array - c++

I have some problems using two dimensional array.
static const int PATTERNS[20][4];
static void init_PATTERN()
{
// problem #1
int (&patterns)[20][4] = const_cast<int[20][4]>(PATTERNS);
...
}
extern void UsePattern(int a, const int** patterns, int patterns_size);
// problem #2
UsePattern(10, PATTERNS, sizeof(PATTERNS)/sizeof(PATTERNS[0]));
In the first statement, I need to cast the const off the two dimensional array PATTERNS. The reason for this is that the init function is called only once, and in the remaining code, PATTERNS is strictly read-only.
In the second statement, I need to pass PATTERNS array to the int** argument. Direct passing resulted a compile error.
I have solved the problem, just about the same time that #Andrey posted the answer. Yes int[][] can't be casted to int**.
It can be casted to int* through &(PATTERNS[0][0]), and the function prototype must be modified with row size (the number of elements in a row). The array can be const_cast away with reference syntax.

Firstly, there's no such thing as cast to array type (or to function type) in C++. Yet this is what you are trying to do. If you want to cast away constness from something, you have to cast to either pointer or reference type. In your case you have a reference on the receiving end of the cast, so the cast itself has to be to reference type as well
int (&patterns)[20][4] = const_cast<int (&)[20][4]>(PATTERNS);
Of course, as Bill already noted, casting away constness from a constant object (and then attempting to modify the object) leads to undefined behavior.
Secondly, a two-dimensional array cannot be passed anywhere as an int ** pointer. If you want to pass your PATTERNS somewhere, you can pass it as const int (&)[20][4], const int (*)[20][4], const int [][4], const int (*)[4] or something similar to that, but not as int **. Do a search on SO and/or read some FAQ on arrays to understand why. This has been explained too many times to repeat it again.

When you declare PATTERNS as const, the compiler may set it up in read-only memory. You can't safely cast away const unless the item was originally declared without const.
I'm guessing that your compiler error was cannot convert 'int (*)[4]' to 'int**' for argument '2' to 'void UsePattern(int, int**, int)'?

AndreyT's answer is perfect. I'd only like to add that I believe you would be better using a class that does the init_PATTERN() work in the constructor and overrides the operator[] to give readonly access to the array elements.
This, of course, assuming you can change the UsePattern function to get a reference to such class instead of a pointer to int array.

C++ Arrays are complicated. You can't just throw them around and expect them to work like in some languages. The only way to initialize an array from another array is to navigate a for loop and copy each item individually. This goes doubly for two-dimensional arrays (meaning you'll need two for loops).
It seems like you're trying to make this more complicated than it needs to be. For instance, if the set of values you will be assigning to PATTERNS will be the same every time you run the program, you can initialize a two dimensional variable like this:
static const int foo[2][3] = {{11,12,13},{21,22,23}};
If the set of values assigned to PATTERNS varies from one execution to the next, then you should probably try to find a different way to approach the problem. I would probably wrap the data in a class, especially if your intention is to use similarly-sized two-dimensional arrays elsewhere in the code.

Related

Why is the size of an array passed to a function by reference known to the compiler in C++?

I know that when I want to pass an array to a function, it will decay into pointer, so its size won't be known and these two declarations are equivalent:
void funtion(int *tab, int size);
and
void funtion(int tab[], int size);
And I understand why. However, I checked that when I pass an array as a reference:
void funtion(int (&tab)[4]);
the compiler will know the size of the array and won't let me pass an array of different size as an argument of this function.
Why is that? I know that when I pass an array by address, the size isn't taken into account while computing the position of the ith element in the array, so it is discarded even if I explicitly include it in the function declaration:
void funtion(int tab[4], int size);
But what is different when I pass an array by reference? Why is its size known to the compiler?
Note: I'm interested in arrays whose size is known at compile time, so I didn't use any templates.
I found a similar question on Stack Overflow, however it doesn't answer my question - it doesn't explain why the compiler knows the size of the array, there is just some information on how to pass arrays to functions.
Because it can, and because checking adds extra safety. The compiler knows the size of the array because you tell it so, right there in the function declaration. And since that information is available, why wouldn't it use it to signal errors in your source code?
The real question is why your last example wouldn't do the same check. This is, unfortunately, another piece of C legacy - you are never passing an array, it always decays into a pointer. The size of the array then becomes irrelevant.
Could a check be added? Possibly, but it would be of limited use (since we are all using std::array now - right!?), and because it would undoubtedly break some code. This, for example:
void func (char Values [4]);
func ("x");
This is currently legal, but wouldn't be with an additional check on array size.
Because there is no odd implicit type change committed by the compiler in the case. Normally when you write:
void func(int[4]);
or
void func(void());
The compiler decides to "help" you and translates those into:
void func(int *);
or
void func(void(*)());
Funny thing though - it wouldn't aid you in such a way when you try returning one of those. Try writing:
int func()[4], func1()();
Ooops - surprise - compiler error.
Otherwise arrays are arrays and have constant size which can be acquired by using the sizeof operator.
This however is often forgotten because of the compiler behavior noted above and also because of the implicit pointer conversion applied to objects of array type when such isn't expected. And this is very often. Though here are the few exceptions when no implicit array object conversion is applied:
size_t arr[4],
(*parr)[3] = &arr, //taking the address of array
(&refarr)[3] = arr, //storing reference to array
sizearrobject = sizeof(arr); //taking the array object size
The above examples will trigger compiler error because of incompatible types on the second and third line.
I'm talking about the cases when arr object isn't automatically converted to something like this:
(size_t*)&arr
Well, there are several ways to pass an array to function. You can pass it by pointer an by reference, and there are ways to define or not to define it's size explicitely for both ways.
In your question you compare these 2 ways:
Pointer to first element: void f(int *arr)
Reference to an entire array: void f(int (&arr)[size])
You ask why you need to specify size only in one of these cases.
It looks like you assume that the only difference between them is the fact that one uses pointer and another uses reference. But this statement is incorrect, they have more differences: One is pointer to first element, but second is a reference to an entire array.
You can pass an array by pointer to an entire array:
void f(int (*arr)[size])
Compare it with your example, with passing by refence to an entire array:
void f(int (&arr)[size])
They are similar, they have similar syntax, they both explicitely define array size.
Also, consider this:
void f(int &arr)
It looks like passing a single int by reference, but you can pass an array of unknown size to it.
Pointer alternative to it is
void f(int *arr)
You ask why you need to specify array size only in one of those cases. It's because of the syntax you used, not because one is pointer and other is reference.
As I said, you can use pointer or reference. And you can specify array size or you can allow an array of any size to be used. These two are not connected.
// by pointer by reference
/* Any size */ void f(int *arr) void f(int &arr)
/* Specific size */ void f(int (*arr)[x]) void f(int (&arr)[x])

Passing array of vectors as a function parameter to change the original values

I have an array of vectors (of ints) and I want to pass it to a member function as reference so it can be modified. (It actually is the output of my function but I already have a return value.)
I wrote something like this
int Dag::dag2array(vector<int> (&aVectors)[4])
{
//some stuff
//calling another function tree2array(aVectors)
//passing the same array as reference
}
It compile and runs although it looks like it is not doing what I want.
In a more or less opposite question (Passing array of vectors as a function parameter (values will not change)), the answers say that the array can be modified without & and that it does not make a copy but it is like a pointer.
Why for a variable like an int one needs the & to avoid
copying and to be able to modify the value of the original variable "on the fly" and not for an array?
Should I use the & or not in my case?
This is one of those cases where C arrays just make life difficult. I would strongly recommend using a std::array (or std::tr1::array if you're not using C++11 yet). Rather than that obscure syntax, saying
int func(std::array<std::vector<int>, 4>& vectors)
makes it very clear that you're passing an array of 4 vectors by reference, and thus can modify the values by saying
vectors[1][2] = 19;
or what-have-you.
When an array is passed to a function, its type is adjusted to a pointer to its first element. Likewise a parameter declaration of the form T[N] is adjusted to T*. The pointer being passed is copied but the elements of the vector are not copied at all. This means when dereferencing the pointer you can still refer to the original array element through the array access syntax array[n] (which is really just pointer arithmetic: *(array + n)).
If you are passing an actual object to a function by value, a copy will occur so if you still want to modify the element you will need a reference.
So no, you do not need to pass the array by reference. Not unless you want to access the size of the array in the function (because the array-to-pointer decay discards the array size).

Passing array to function C++

I have one quick question about the passing of arrays in C++ which I don't understand.
Basically when you want to pass a array of type integer to another function you have to pass an address to that array instead of directly passing the whole block of contiguous memory. Exactly why is the case?
Also, why is that char arrays can directly be passed to another function in C++ without the need to pass an address instead??
I have tried looking for learning materials for this online (such as cplusplus.com) but I haven't managed to find and explanation for this.
Thanks for your time, Dan.
As long as C++ is concerned, passing char arrays and int arrays are same.
There are 2 ways to pass arrays in c++.
Address is passed
int fn(int *arrays, int len);
int fn(int arrays[], int len); // Similar to above, still staying as sytax hangover from anci c
Array reference is passed
int fn(int (&array)[SIZE]); // Actual array passed as reference
You can templatized above function as
template<size_t SIZE>
int fn(int (&array)[SIZE]);
Above method allows you to pass array of anysize to this function. But beware, a different function is created from template for each size. If your function's side effect changes a local state (static variable for ex), this should be used with care.
If you don't want to change contents, use const with arguments.
If you want a copy of array in function argument, consider using stl container like std::array or std::vector or embed array in your class.
It isn't entirely clear from your question exactly what you're trying and what problems you've had, but I'll try to give you useful answers anyway.
Firstly, what you're talking about is probably int[] or int* (or some other type), which isn't an array itself... its a pointer to a chunk of memory, which can be accessed as if it were an array. Because all you have is a pointer, the array has to be passed around by reference.
Secondly, passing around an array as a "whole block of contiguous memory" is rather inefficient... passing the point around might only involve moving a 32 or 64 bit value. Passing by reference is often a sensible thing with memory buffers, and you can explicitly use functions like memcpy to copy data if you needed to.
Thirdly, I don't understand what you mean about char arrays being "directly" passable, but other types of arrays cannot be. There's nothing magic about char arrays when it comes to passing or storing them... they're just arrays like any other. The principle difference is that compilers allow you to use string literals to create char arrays.
Lastly, if you're using C++11, you might want to consider the new std::array<T> class. It provides various handy facilities, including automatic memory management and keeping track of its own size. You can pass these by value, template<class T> void foo(std::array<T> bar) or by reference template<class T> void foo(std::array<T>& bar), as you like.
You can't pass any array by value. You can pass by value either a struct containing array or std::array from C++11.

Cannot convert from 'int *' to 'int []'?

I know this might be a common question but I have tried to search but still cannot find a clear answer.
I have the following code:
int* f() {
int a[] = {1,2,3};
return a;
}
int main() {
int a[] = f(); // Error here
getch();
return 0;
}
This code produces the error message: "Cannot convert from 'int *' to 'int []'"
I found this quite strange because I have read that pointer and array are similar. For example, we can use a[i] instead of *(a + i).
Can anyone give me a clear explanation, please?
There are actually two errors in this code.
Firstly, you are returning the address of a temporary (the int array within f), so its contents are undefined after the function returns. Any attempt to access the memory pointed to by the returned pointer will cause undefined behaviour.
Secondly, there is no implicit conversion from pointers to array types in C++. They are similar, but not identical. Arrays can decay to pointers, but it doesn't work the other way round as information is lost on the way - a pointer just represents a memory address, while an array represents the address of a continuous region, typically with a particular size. Also you can't assign to arrays.
For example, we can use a[i] instead of *(a + i)
This, however, has little to do with the differences between arrays and pointers, it's just a syntactic rule for pointer types. As arrays decay to pointers, it works for arrays as well.
The type int[] doesn't actually exist.
When you define and initialize an array like
int a[] = {1,2,3};
the compiler counts the elements in the initializer and creates an array of the right size; in that case, it magically becomes:
int a[3] = {1,2,3};
int[] used as a parameter to a function, instead, it's just plain int *, i.e. a pointer to the first element of the array. No other information is carried with it, in particular nothing about the size is preserved. The same holds when you return a pointer
Notice that an array is not a pointer: a pointer can be changed to point to other stuff, while an array refers always to the same memory; a pointer does not know anything about how big is the space of memory it points to, while the size of an array is always known at compile time. The confusion arises from the fact that an array decays to a pointer to its first element in many circumstances, and passing it to a function/returning it from a function are some of these circumstances.
So, why doesn't your code work? There are two big errors:
You are trying to initialize an array with a pointer. We said that an int * doesn't carry any information about the size of the array. It's just a pointer to the first element. So the compiler cannot know how big a should be made to accomodate the stuff returned by f().
In f you are returning a pointer to a variable that is local to that function. This is wrong, because a pointer does not actually store the data, it only points to where the data is stored, i.e. in your case to the a local to f. Because that array is local to the function, it ceases to exist when the function exits (i.e. at the return).
This means that the pointer you are returning points to stuff that does not exist anymore; consider the code:
int * a = f();
This initialization works, and you can try to use a later in the function, but a will be pointing to the no-longer existent array of f; in the best case your program will crash (and you'll notice immediately that you've done something wrong), in the worst it will seem to work for some time, and then start giving strange results.
int * and int [] are similar but different.
int * is a real pointer, meanwhile int[] is an array reference ( a sort of "constant pointer" to the begin of the data) wich cannot be modified. So, a int * can be threated like a int [] but not viceversa.
You can use a[b] and*(a+b) interchangeably because that is exactly how a[b] is defined when one of a or b is a pointer and the other is of integer or enumeration type.
Note: This also means that expressions like 42[a] are perfectly legal. Human readers might object strongly, but the compiler won't bat an eye at this.

pass by reference c++

My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function.
I have some really big vectors that I'm passing around in my program. All the vectors will be modified inside the functions. My matrices are of sizes about [256*256][256][50]...
Is there some particular reason not to use call-by reference here?
AFAIK call by reference should be way faster and consume less memory?
Besides all common discussions on when and how to pass by possibly const reference for non-primitive types, arrays are quite special here.
Due to backwards compatibility with C, and there due to your specific problem: arrays can be huge, arrays are never really passed by value in either C or C++. The array will decay into a pointer to the first element, so when you write:
void foo( type array[100] );
The compiler is actually processing:
void foo( type *array );
Regardless of what the size of the array is (two common pitfalls there: trusting that array is an array inside foo and believing that it will be guaranteed to be 100 elements on it.
Now, in C++ you can actually pass arrays by reference, but the reference must be of the concrete type of the array, that includes the size:
void foo_array( type (&array)[100] );
The funny syntax there is telling the compiler that the function will take an array of exactly 100 elements of type type. The advantage there is that the compiler can perform size checking for you:
// assuming 'type' is defined
int main() {
type array0[99];
type array1[100];
foo( array0 ); // compiles, but if size=100 is assumed it will probably break
// equivalent to: foo( &array0[0] )
// foo2( array0 ); // will not compile, size is not 100
foo2( array1 ); // compiles, size is guaranteed to be 100
}
Now, the problem is that your function will only work for an array of exactly 100 elements, and in some cases, you might want to perform the same operation in different array sizes. The two solutions are: template the function in the size of the array which will provide a size-safe implementation for each used size --greater compile time and binary size, the template is compiled for every different size-- or using the pass-by-value syntax, which will make the array decay --not safe in size, that must be passed as extra argument, lesser compile time and binary size. A third option is combining both:
void foo( type *array, int size );
template <size_t N>
void foo( type (&array)[N] ) {
foo( array, N );
}
In this case, while there will be one templated foo for each size, the compiler will most probably inline the call and the generated code would be equivalent to the caller providing the array and size. No extra computations needed and type safety for real arrays.
Now, pass-by-reference is very rarely used with arrays.
My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function.
It should be used when you are not changing something inside the function or you change things and want the changes to be reflected to the original array or don't care about the changes to be reflected in the original array.
It shouldn't be used if you don't want your function to change your original array (you need to preserve the original values after the call) and the callee function changes the values of the passed argument.
Your teacher is wrong. If you need to modify arrays, pass by reference is the way to go. If you don't want something modified, pass by const reference.
To prevent accidental changes, use pass-by-const-reference; that way, by default*, the passed-in array can't get changed by the called function.
* Can be overridden with const_cast.
You can pass by reference if:
you won't modify passed object
you want to modify object and don't want to keep old object untouched
When you pass something by reference, then only pointer is passed to function. If you pass whole object then you need to copy it, so it will consume more cpu and memory.
Generally speaking, objects should always be passed by reference. Otherwise a copy of the object will be generated and if the object is substantially big, this will affect performance.
Now if the method or function you are calling does not modify the object, it is a good idea to declare the function as follows:
void some_function(const some_object& o);
This will generate a compile error if you attempt to modify the object's state inside the function body.
Also it should be noted that arrays are always passed by reference.
Hold on a second.. I'm scared at how people are answering this one. Arrays, as far as I remember, are always passed by reference.
void function(int array[])
{
std::cout << array[0] << '\n';
}
// somewhere else..
int array[2] = { 1, 2 };
function(array); // No copy happens here; it is passed by reference
Further, you can't say the array argument is a reference explicitly, as that would be the syntax for creating an array of references (something that's not allowed).
void function(int &array[]) // error here
{ /* ... */ }
So what do you mean?
Further, many are saying that you should only do that if you modify the contents of the array inside the function. Then, what about reference-to-const?
void function(const int arr[])
{
std::cout << arr[0] << '\n';
}
-- edit
Will somebody please point me out how to not pass an array by reference in C++?
-- edit
Oh, so you're talking about vectors. Okay, then the rules of thumb are:
Pass by reference only when you want to modify the contents of the vector.
Pass by reference-to-const whenever you can.
Pass by value only when the object in question is really, really small (like a struct containing an integer, for example), or when it makes sense to (can't think of a case out of the top of my head).
Did I miss something?
-- edit
In the case of plain C arrays, it's a good idea to pass them by reference (like in void function(int (&array)[100])) when you want to ensure that the array has a given definite size.
Thanks, dribeas.
Usually, in introductory courses, they tell you that so you don't accidentally change something you didn't want to.
Like if you passed in userName by reference, and accidentally changed it to mrsbuxley that probably would cause errors, or at the very least be confusing later on.
I don't see any reason why you can't pass by reference. Alternatively you could pass pointers around, but I think pass by reference is better sometimes as it avoids null pointer exceptions.
If your teacher has suggested this as some kind of convention, then feel free to break it if it makes sense to. You can always document this in a comment above the function.
Our house style is to NEVER pass an object by value but to always pass a reference or const reference. Not only do we have data structures that can contain 100s of MB of data and pass by value would be an application killer, but also if we were passing 3D points and vectors by value the our applications would grind to a halt.
It is always a good choice to pass object by reference but we need to be careful and first we have to decide what is our purpose/ purpose of our function?
You have to make a choice here, whether we are gonna only read the data of an object or modify it.
Suppose you got an interface like
void increament_value(int& a);
so in this you can modify value an object which we are passing, but it is a disaster when you passing your sensitive data, you might lose you original data and can not revert it, right?
so c++ provides you a functionality to not to change the value of an object whose reference you are passing to a function, and it is always a good choice to pass a const reference of an object for e.g.,
double get_discounted_amount(const double &amount,double discount){
return (amount*discount/100);
}
This guarantees that your actual value of an object is not gonna change, but again it depends on purpose of your interface whether you wanna change it or only use(read) it