I am new to C++ and have done only MATLAB earlier.
My Q is about the input argument of the following functions, which call variables by value,reference and pointer.
void SwapbyValue (int a, int b){
// Usual swapping code
}
void SwapbyRef (int &a, int &b){
// Usual swapping code
}
void SwapbyPoint(int *a,int *b){
//Usual swapping code
}
Since my Q isn't about how the above functions work but rather about how I call them, I've left out the code. So, I understand we call the above functions by typing SwapbyRef (i1,i2),SwapbyRef (i1,i2) and SwapbyPoint(&i1,&i2) when i1 and 12 are int.
That confuses me the life out of me. Okay, I get that the first function takes in values and makes sense. But in the second one, calling by just i1 and i2 doesn't make sense as when the function is defined, we set its input as &a and not just a but it still runs. Again in the third, we set the input argument as a pointer i.e. *a but we're passing an address &a (like 0x7956a69314d8) when we call it.
Why does it run when we pass the wrong kind of input to the function?
For example,a Matlab analogy,it looks like passing a char to a int function. Help!
int &a is a reference to an int, meaning, it will accept all int variables that already exist. What you cannot do is for example SwapbyRef(4, 5) using SwapbyRef (int &a, int &b), because 4 and 5 are temporary ints that do not exist somewhere in memory as variables.
Btw, you should probably just look up what a reference in c++ is. That would help you most, I think.
Related
I got this declaration from https://en.cppreference.com/w/cpp/language/scope, but don't know how to parse this declaration even there is a comment below.
my questions is
how to parse the declaration statement (I see it as a function pointer to a function protocol like "int[3] foo(int n)" or "int foo(int n)[3] --- they are illegal in C++ )? Then, how can I construct a concrete function which can be assigned to this function pointer? Thanks.
const int n = 3;
int (*(*f2)(int n))[n]; // OK: the scope of the function parameter 'n'
// ends at the end of its function declarator
// in the array declarator, global n is in scope
// (this declares a pointer to function returning a pointer to an array of 3 int
It's a pointer to a function taking an int and returning a pointer to an int array of size three.
All the comment is saying is that there are two n identifiers in play here. The [n] (in array declarator) is using the const int 3, not the parameter to the function (which is in the function declarator).
Starting in the middle, with each segment being included in the subsequent bullet point as ...:
f2 is a pointer, (*f2).
It's a pointer to a function taking an integer, ...(int).
It returns a pointer to an int array of size three, int (*...)[3].
You can form a concrete function for it as per the following complete program, which output the first element, 42:
#include <iostream>
const int n = 3;
int (*(*f2)(int n))[n];
int (*g2(int))[n] {
static int x[::n] = { 42 }; // Use outer n, not the parameter.
return &x; // since C++ has no VLAs. This
// means parameter is not actually
// needed in this test case, though
// it may be in more complicated
// tests.
}
int main() {
f2 = &g2; // Assign concrete function to pointer.
auto y = f2(3); // Call via pointer, get array.
std::cout << *(y[0]) << '\n'; // Deref first element to get 42.
}
Having said that, I would be rather curious if one of my colleagues submitting something like that for a code review, at least without a large comment explaining it. Although seasoned developers may be able to work it out, those less experienced may have trouble.
And, in fact, even seasoned developers shouldn't have to work it out, especially given it took me a few minutes.
C++ has a very expressive type system which can easily build something like this up in parts, so you don't have to experience migraines trying to work it out. For something like this, I'd be using std::vector (or std::array) unless there was a compelling case for the added complexity caused by more basic types.
You can create a type for pointer to an array of 3 int
typedef int (*array_with_size_n)[n];
and then use it as return type
const int n = 3;
int (*(*f2)(int n))[n];
int arr[n];
array_with_size_n func(int n)
{
return &arr;
}
int main()
{
f2 = &func;
return 0;
}
i was just playing with pointers as function arguments and i know this.
#include <iostream>
using namespace std;
void func(int *a)
{
*a+=1;
return;
}
int main()
{
int a=1;
cout<<a<<endl;//prints 1
func(&a);
cout<<a;//prints 2
return 0;
}
My question is why does below code act similar to the one above, more precisely
when we call func(&a) from main function in above case
// starting address of that 4 bytes(size of int) of data gets passed and in our function(func) this address is stored in local pointer 'a' and when we write *(a) our compiler knows to read 4 bytes of data because its an integer pointer.
in short, my question is
what exactly are we passing to 'func'
when we call func(a) where 'a' is a variable which stores an integer value
and what exactly func(int &a) means
#include <iostream>
using namespace std;
void func(int &a)
{
//cout<<*a;// error
a+=1;
// cout<<a<<endl;
}
int main()
{
int a=1;
cout<<a<<endl;// prints 1
func(a);
cout<<a;// prints 2
return 0;
}
sorry for bad english
One way to read pointers and references is that during declarations, the '*' can be replaced by "something that points to".
So:
int* a;
Means that 'a' is something that points to an integer (i.e. 'a' is a pointer).
In other places in the code (not declarations), the '*' can be replaced by "the thing pointed to by".
So:
*a = 5;
Means that "thing pointed to by 'a' becomes equal to 5". I.e. the integer which a points to is now 5.
In your first block of code, 'a' is just an integer type. when you write func(&a);, you are passing the address of 'a' (i.e. the name of the memory location which stores the value of 'a') to the function. The function is expecting an int* type, (something which points to an int), which is exactly what you've given it.
Within the function, 'a' is just the address of your variable. The function then takes this address, and says "increment the thing that 'a' points to".
In your secondblock of code, 'a' is again just an integer type. This time however, the function is expecting a reference variable (because the function definition is expecting an int& type.
So within the function, 'a' is the original variable - not a copy or a pointer to the original variable. The function says "increment the actual integer that was sent".
Read more
The two cases work similarly:
Case 1: func expects some pointer to some direction of an integer (int *a) which is, as you said, the first byte of a sizeof (int) bytes block according to the OS. When func is called you passed correctly that direction func(&a), so the compiler considers that call as something like: int p = &a; func(p); anyway a pointer to that direction is actually what is being passed.
Case 2: func expects some direction of some integer (int &a). When func is called you just passed correctly the value func(a), as all C++ compilers support reference paramenters, the compiler passes internally the direction of the passed value, func (&a). Notice if you try to call func like func (&a) an error will occur because it would be passed something like func (&&a) while the compiler is just waiting for (&a).
OBS: We can also look to the second case void func(int &a) as a reference which is different from a pointer with an example:
int a = 10;
int &b = a;
cout<<a; //10 is printed
cout<<b; //10 is printed
b = 20;
cout<<a; //20 is printed
cout<<b; //20 is printed
Whether you modify a reference to a (i.e b) or you modify a directly, you are modifying the same value beacause they stand at the same direction of a.
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.
my question is:
I saw(in CUDA examples) that it is possible to use one of the input arguments of a function as output variable. Example: add two integers, c=a+b:
void function AddT(int a,int b,int c){
c=a+b;
}
But this will not work. The function will not alter the value of c in the main program. Who can I fix it and allow the function to change the value of c?
Pass the variable c by reference.
void function AddT(int a, int b, int& c)
{
c = a + b;
}
This will make it so that any changes to c that you make in the function will remain even after the function ends. My wording is pretty poor here; you can look here for more information:
Pass by Reference / Value in C++
What's the difference between passing by reference vs. passing by value?
What is more efficient: Call by pointer or by value? I think it is call by pointer, because passing a pointer to a variable does not use as much memory as creating a copy of a variable. Am I wrong?
main(){
int a, b;
a = 10;
b = 5;
gcf(&a, &b);
return 0;
}
int gcf(int* c, int* d){
int val1=*c;
int val2=*d;
//...
}
In nearly all code, as long as we're dealing with small/simple objects, the overhead of copying the object, vs. passing it as a pointer or reference is pretty small.
Obviously, if we make a std::string with a large chunk of text in it, it will take quite some time to copy it, relative to just passing a reference.
However, the primary objecting ANY TIME when writing code is to focus on correctness. If you have "large" objects, then use const Type &val if the value is not being modified - that way, you can't accidentally modify it. If the object is to be modified, then you NEED to use a reference or pointer to get the updates back to the caller of the function.
It is entirely possible to make code that runs noticeably slower with a reference than with a value. I was once looking into the performance of some code that we were working on, and found a function that looked something like this:
void SomeClass::FindThing(int &thing)
{
for(thing = 0; someVector[thing] != 42; thing++)
;
}
It really looks rather innocent, but since each update of thing means an indirect memory access [at least in the compiler we used, which was certainly not "rubbish"], it was taking quite a lot of time out of the entire process [it was also called twice as much as necessary].
I rewrote it as:
void SomeClass::FindThing(int &thing)
{
for(int i = 0; someVector[i] != 42; i++)
;
thing = i;
}
And the function ran about 4x faster. Taking out the second, unnecessary call, as well, and we ended up with about 30% faster runtime. This was in a "fonts benchmark", and this was one out of a several dozen functions involved in the "draw fonts to screen". It's scary how a simple, innocent looking function can make a BIG difference to performance.
For types smaller than the size of a pointer (e.g. int), passing by value is more efficient.
For types bigger than the size of a pointer (e.g. most struct or class instances), passing by reference is probably more efficient (only "probably" because on top of the cost of passing the parameter, potentially constructing an object, you incur the cost of dereferencing your parameter every time you use it).
More details about passing-by-value vs. passing-by-reference can be found in this question. More details about reference vs. pointer arguments can be found in that question.
In your example of code snippet
main(){
int a, b;
a = 10;
b = 5;
}
int gcf(int* c, int* d){
int rem;
int val1=*c;
int val2=*d;
//...
}
there is no any sense to pass variables a and b to the function indirectly using pointers if you are not going to change them. In this case the code is ineffective because that to get values of *c and *d the compiler will need to generate more instructions.
And you are wrong saying that
passing a pointer to a variable does not use as much memory as
creating a copy of a variable. Am I wrong?
Usually pointers are equal to or even larger than the size of type int. For exaple in a 64-bit system sizeof( int ) can be equal to 4 while sizeof( int * ) can be equal to 8.
There is a sense to pass an object indirectly by pointers (usually in C programs) when the size of the object is much larger than the size of the pointer.
In C++ instead of pointers usually references are used.
For example
#include <iostream>
#include <string>
inline void print_reverse( const std::string &s )
{
std::cout << std::string( s.rbegin(), s.rend() ) << std::endl;
}
int main()
{
std::string s( "Hello World" );
print_reverse( s );
}
Here const std::string &s defined reference to an object of type std::string.