I have a question about passing std::array into function - c++

I'm learning c ++ And the syntax of putting a std::array into the function confuses me.
#include <iostream>
#include <array>
using namespace std;
void printArray(const std::array<int, 5> &n)
{
std::cout << "length: " << n.size() << endl;
for (int j = 0; j < n.size(); j++ )
{
cout << "n[" << j << "] = " << n[j] << endl;
}
}
int main()
{
array<int, 5> n = {1,2,3,4,5};
printArray(n);
return 0;
}
I want to ask about 'const', what role does it play and what effect does it have if not using it?
Why do we have to use &n while the name of an array is already pointer

Depending on the argument you can do certain assumptions about the function.
void printArrayA(std::array<int, 5> n)
If I call printArrayA then the array I pass to it is copied, so the function can't do changes to the array I pass, but has an overhead of copying the array.
void printArrayB(std::array<int, 5> &n)
If I call printArrayB then the array I pass to it is not copied, the function could do changes on the array, or on the elements stored in the array.
void printArrayC(const std::array<int, 5> &n)
If I call printArrayC then the array I pass to it is not copied, and because it is const the function can't do any changes on that array or on its elements. (Well I, in theory, could cast away the const, but that's not something that should be done, a const should indicate the caller, that the object won't be changed)

void printArray(const std::array<int, 5> &n)
What this does is to allow you to pass in to the function an unchangeable (without const-casting it, anyway) reference to the std::array. The reference is a lot smaller than the array itself, typically just a pointer, and the const bit ensures the function does not attempt to change the underlying object.
It's usually used to ensure you don't copy "large" things where unnecessary, things like vectors, arrays or strings.

In this case const means that printArray will not modify the object passed to it.
An std::array is not a C-style array (such ase int a[10]), so you are not passing a pointer, you are passing a reference to an std::array object.

Your question is not only about 'std::vector', it is about 'const' and 'references'.
'const' keywords means that you can call only 'const' method of that class, means that (assume that the used class is implemented correctly) you can't modify this class in that method.
'&' means that you pass the parameter by 'reference' and not by 'value', if you are not familiar with that difference you may want to read this: Value vs. Reference

As others have mentioned, the name of a std::array does not decay to a pointer. To convert to a pointer, you would call .data().
Why do you want to pass by (const) reference, and why does a foo[]decay to a foo* const in many contexts?
You (practically) never want to copy arrays. It takes a huge amount of time and memory. You always want to pass them to a function by reference. On top of that, most algorithms that work on arrays are supposed to work on arrays of any size. (Brian Kernighan, the K in K&R, particularly considered it a flaw in Pascal that the size of an array is part of its type.) Therefore, back in the ’70s, the designers of C made a rule that passing an array to a function is the same as passing a pointer to its first element.
C++ stuck with that for the sake of backward compatibility: a lot of programmers compile C code in C++ compilers. One famous pitfall is trying to take the sizeof an array parameter in C++. Because array parameters decay to pointers, this gives you the size of a pointer. In C++, you have the option of passing a type (&name)[size] instead; that is, passing a type[size] by reference. This preserves the size as part of the type. (C also got some new syntax in 1999 that never made it over to C++, including the ability to pass the size of an array parameter.)
In C++, a std::array has no special syntax and works like any other type. You never want to copy an entire array that you aren’t going to modify. You still want to pass arrays by reference, so you use the standard syntax for that: &. Whenever you don’t need to modify a parameter, you declare it const. This helps the compiler detect logic errors and, sometimes, optimize.

Related

Making a vector with user input and printing it out [duplicate]

I'm coding in C++. If I have some function void foo(vector<int> test) and I call it in my program, will the vector be passed by value or reference? I'm unsure because I know vectors and arrays are similar and that a function like void bar(int test[]) would pass test in by reference (pointer?) instead of by value. My guess is that I would need to pass the vector by pointer/reference explicitly if I wanted to avoid passing by value but I'm not sure.
In C++, things are passed by value unless you specify otherwise using the &-operator (note that this operator is also used as the 'address-of' operator, but in a different context). This is all well documented, but I'll re-iterate anyway:
void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference
You can also choose to pass a pointer to a vector (void foo(vector<int> *bar)), but unless you know what you're doing and you feel that this is really is the way to go, don't do this.
Also, vectors are not the same as arrays! Internally, the vector keeps track of an array of which it handles the memory management for you, but so do many other STL containers. You can't pass a vector to a function expecting a pointer or array or vice versa (you can get access to (pointer to) the underlying array and use this though). Vectors are classes offering a lot of functionality through its member-functions, whereas pointers and arrays are built-in types. Also, vectors are dynamically allocated (which means that the size may be determined and changed at runtime) whereas the C-style arrays are statically allocated (its size is constant and must be known at compile-time), limiting their use.
I suggest you read some more about C++ in general (specifically array decay), and then have a look at the following program which illustrates the difference between arrays and pointers:
void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
foo1(arr);
foo2(arr);
foo3(arr);
foo4(arr);
}
A vector is functionally same as an array. But, to the language vector is a type, and int is also a type. To a function argument, an array of any type (including vector[]) is treated as pointer. A vector<int> is not same as int[] (to the compiler). vector<int> is non-array, non-reference, and non-pointer - it is being passed by value, and hence it will call copy-constructor.
So, you must use vector<int>& (preferably with const, if function isn't modifying it) to pass it as a reference.
void foo(vector<int> test)
vector would be passed by value in this.
You have more ways to pass vectors depending on the context:-
1) Pass by reference:- This will let function foo change your contents of the vector. More efficient than pass by value as copying of vector is avoided.
2) Pass by const-reference:- This is efficient as well as reliable when you don't want function to change the contents of the vector.
when we pass vector by value in a function as an argument,it simply creates the copy of vector and no any effect happens on the vector which is defined in main function when we call that particular function.
while when we pass vector by reference whatever is written in that particular function,
every action will going to perform on the vector which is defined in main or other function when we call that particular function.

Why use C++ container "array" rather than traditional C array?

Popular opinion is that C++ array is safer with almost equal efficiency. Except for checking whether the index is out of range and not allowing implicit type cast to pointer, are there any other features?
Besides, why implicit type cast of traditional C array is regarded as a bad way?
I'm not very good at C++(also at English),plz forgive me if this question is not worth an answer. Thank you!
The main benefit is that a std::array is a first-class object in C++, which means you can do all the things with it that you can do with any other "normal" C++ object.
A traditional C array, on the other hand, is not a first-class object, which means a lot of things won't work:
#include <array>
// Works!
std::array<int, 5> ReturnAStdArrayOfSixes()
{
std::array<int, 5> ret;
ret.fill(6);
return ret;
}
// Doesn't compile, sorry
int[5] ReturnACArrayOfSixes()
{
int ret[5];
for (int i=0; i<5; i++) ret[i] = 6;
return ret;
}
int main(int, char **)
{
std::array<int, 5> stdArray1;
std::array<int, 5> stdArray2;
int cArray1[5];
int cArray2[5];
stdArray1 = stdArray2; // works
cArray1 = cArray2; // error: array type 'int [5]' is not assignable
if (stdArray1 < stdArray2) {/* do something */} // compares arrays' contents lexographically
if (cArray1 < cArray2) {/* do something */} // compiles, but compares pointers which probably isn't what you wanted
return 0;
}
As for "implicit type cast of traditional C array" (by which I think you mean the implicit decay of an array-type into a pointer-type), that's a useful mechanism but it can bite you if you aren't expecting it, e.g.:
// This code works as expected
int myArray[5];
cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";
Now let's refactor the above code into a nice function so we can re-use it:
void PrintArraySize(int myArray[5])
{
std::cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";
}
int main(int, char **)
{
int myArray[5];
PrintArraySize(myArray);
return 0;
}
... Oh noes! Now PrintArraySize() is buggy, and prints a number much smaller than the number of items in the array! (The reason is that myArray in the function has implicitly decayed to a pointer, so sizeof(myArray) in the function evaluates to the sizeof(int *), e.g. 4 or 8 bytes, rather than the size of the contents of the passed-in array)
Not sure what you exactly meant by your question about the implicit cast of a C array, but I'm guessing you meant either casting implicitly the values stored inside (like in int a[10]; float f=a[0]), or casting the implicit pointer to the first element (like in int a[10]; void* p=a;). Anyway, casting any pointer to void* pointer implicitly is ok (you just need to know what is the size of the memory stored at such pointer if you want to read it), because void* pointers aren't really meant for data manipulation, so whenever you use a void* pointer, you know what you are doing, right?
But a bit more seriously now - implicit casting, in general, is something that the compiler does according to the language rules, without asking the programmer if it is what was actually desired. That's why it sometimes can lead to errors in the code (programmer's oversight, or incorrect assumptions as to what is happening during such a cast).
When you cast explicitly, then, first of all, you make sure that you get the desired result. But what is more important, if your explicit cast gives ambiguous result for the compiler, or even it turns out impossible to the compiler, then the compiler will inform you about that, and you will be able to revise your casting decisions early and prevent bugs in your code.
So explicit casting is just a way to talk to the compiler more strictly, making sure that it understands better what you meant when you wrote your code. Then, in return, the compiler gives you hints when you cast something incorrectly (with implicit casting it would do things its own way, and you wouldn't even know when the effect of such a cast was different than you wanted).

While passing an array through a function in C++/C, why address of array is used in actual parameter whereas the array in formal parameter?

#include <iostream>
using namespace std;
int func(int ar[5]){
//the code is written here with returning whatever the requirement is
}
int main(){
int ar[5];
func(ar);
return 0;
}
In this kind of situation where we are passing array through a function why the address of the array is used in actual parameter whereas the array in formal parameter?
This is because C handled arrays weirdly.
In C, arrays convert to a pointer to their first element at the drop of a hat, cannot be passed as arguments to a function, cannot be returned from functions, and cannot be copied by assignment.
C++, originally based off C, carries these screwed up design decisions as a legacy issue. Fixing them would break insane amounts of code.
If you want an array that behaves more reasonable, use std::array.
void foo(int[5]);
this is actually taking an int* argument.
int arr[7];
foo(arr);
this converts the 7 element arr to a pointer and passes it to foo. Which seems to take int[5] but that 5 does nothing.
Yes this is utterly crazy.
Now,
void bar(int(&)[5])
because C does not have references, the above is an actual reference to an array if 5 elements, so
bar(arr)
won't compile.
There is nothing weird, nor screwed up about how arrays are passed in C. C is expressed pretty simply, really. C /does/ have references; they are explicit, so, easy to see when they're in use. We call them pointers.
One simply needs to understand that there is not dedicated storage for array types, that arrays are not first-class types, so, won't behave like first-class types. Can't be assigned into (directly), nor passed into and out of functions directly.
In C/C++ we use pointers to refer to a chunk of memory where the contents of the array are stored.
So, all that's left is that we understand that when we declare an array, the name of the array is really a pointer to the beginning of the array.
int a[12] ;
/* a's type is this: */
int *a ;
So, when we "pass an array" to a function, we are copying the pointer into the function. The semantics are straightforward, and entirely consistent (unlike Java).
The array, itself, is never passed directly.
Finally, realise that there is no difference between a pointer to a single integer, and a pointer to a contiguous chunk of integers in memory.
Remember, a[i] is equivalent to *(a+i). So, in this example:
int i = 12 ;
int *p = &i ;
, *p is the same as *(p+0); the p can be thought of as an array of length 1.
With a slight change in perspective you should be able to see the simplicity, the elegance, that is C.

C++ Separating elements of a vector with a comma [duplicate]

I'm coding in C++. If I have some function void foo(vector<int> test) and I call it in my program, will the vector be passed by value or reference? I'm unsure because I know vectors and arrays are similar and that a function like void bar(int test[]) would pass test in by reference (pointer?) instead of by value. My guess is that I would need to pass the vector by pointer/reference explicitly if I wanted to avoid passing by value but I'm not sure.
In C++, things are passed by value unless you specify otherwise using the &-operator (note that this operator is also used as the 'address-of' operator, but in a different context). This is all well documented, but I'll re-iterate anyway:
void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference
You can also choose to pass a pointer to a vector (void foo(vector<int> *bar)), but unless you know what you're doing and you feel that this is really is the way to go, don't do this.
Also, vectors are not the same as arrays! Internally, the vector keeps track of an array of which it handles the memory management for you, but so do many other STL containers. You can't pass a vector to a function expecting a pointer or array or vice versa (you can get access to (pointer to) the underlying array and use this though). Vectors are classes offering a lot of functionality through its member-functions, whereas pointers and arrays are built-in types. Also, vectors are dynamically allocated (which means that the size may be determined and changed at runtime) whereas the C-style arrays are statically allocated (its size is constant and must be known at compile-time), limiting their use.
I suggest you read some more about C++ in general (specifically array decay), and then have a look at the following program which illustrates the difference between arrays and pointers:
void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
foo1(arr);
foo2(arr);
foo3(arr);
foo4(arr);
}
A vector is functionally same as an array. But, to the language vector is a type, and int is also a type. To a function argument, an array of any type (including vector[]) is treated as pointer. A vector<int> is not same as int[] (to the compiler). vector<int> is non-array, non-reference, and non-pointer - it is being passed by value, and hence it will call copy-constructor.
So, you must use vector<int>& (preferably with const, if function isn't modifying it) to pass it as a reference.
void foo(vector<int> test)
vector would be passed by value in this.
You have more ways to pass vectors depending on the context:-
1) Pass by reference:- This will let function foo change your contents of the vector. More efficient than pass by value as copying of vector is avoided.
2) Pass by const-reference:- This is efficient as well as reliable when you don't want function to change the contents of the vector.
when we pass vector by value in a function as an argument,it simply creates the copy of vector and no any effect happens on the vector which is defined in main function when we call that particular function.
while when we pass vector by reference whatever is written in that particular function,
every action will going to perform on the vector which is defined in main or other function when we call that particular function.

Are vectors passed to functions by value or by reference in C++

I'm coding in C++. If I have some function void foo(vector<int> test) and I call it in my program, will the vector be passed by value or reference? I'm unsure because I know vectors and arrays are similar and that a function like void bar(int test[]) would pass test in by reference (pointer?) instead of by value. My guess is that I would need to pass the vector by pointer/reference explicitly if I wanted to avoid passing by value but I'm not sure.
In C++, things are passed by value unless you specify otherwise using the &-operator (note that this operator is also used as the 'address-of' operator, but in a different context). This is all well documented, but I'll re-iterate anyway:
void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference
You can also choose to pass a pointer to a vector (void foo(vector<int> *bar)), but unless you know what you're doing and you feel that this is really is the way to go, don't do this.
Also, vectors are not the same as arrays! Internally, the vector keeps track of an array of which it handles the memory management for you, but so do many other STL containers. You can't pass a vector to a function expecting a pointer or array or vice versa (you can get access to (pointer to) the underlying array and use this though). Vectors are classes offering a lot of functionality through its member-functions, whereas pointers and arrays are built-in types. Also, vectors are dynamically allocated (which means that the size may be determined and changed at runtime) whereas the C-style arrays are statically allocated (its size is constant and must be known at compile-time), limiting their use.
I suggest you read some more about C++ in general (specifically array decay), and then have a look at the following program which illustrates the difference between arrays and pointers:
void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
foo1(arr);
foo2(arr);
foo3(arr);
foo4(arr);
}
A vector is functionally same as an array. But, to the language vector is a type, and int is also a type. To a function argument, an array of any type (including vector[]) is treated as pointer. A vector<int> is not same as int[] (to the compiler). vector<int> is non-array, non-reference, and non-pointer - it is being passed by value, and hence it will call copy-constructor.
So, you must use vector<int>& (preferably with const, if function isn't modifying it) to pass it as a reference.
void foo(vector<int> test)
vector would be passed by value in this.
You have more ways to pass vectors depending on the context:-
1) Pass by reference:- This will let function foo change your contents of the vector. More efficient than pass by value as copying of vector is avoided.
2) Pass by const-reference:- This is efficient as well as reliable when you don't want function to change the contents of the vector.
when we pass vector by value in a function as an argument,it simply creates the copy of vector and no any effect happens on the vector which is defined in main function when we call that particular function.
while when we pass vector by reference whatever is written in that particular function,
every action will going to perform on the vector which is defined in main or other function when we call that particular function.