I'm trying to make a function that reduces a certain integer value by 30.
#include <iostream>
using namespace std;
int valuered(int value)
{
value-=30;
}
int main()
{
int number{100};
valuered(number);
cout<<number;
return 0;
}
You are passing value by value, meaning the valuered function has a local copy of the argument. If you want to affect the outside variable number the function should look like this:
void valuered(int& value)
{
value-=30;
}
Here value is being passed by reference, meaning any changes done to it inside the function will propagate to the actual argument that has been passed in.
Also note that I have changed the return type from int to void, since you are not returning anything. Not returning anything from a function declared to return a value makes the program have undefined behavior.
pass by reference is important to use the modified value out side the function because if you are using pass by value then the change in value will only exist inside the user defined function.
#include<iostream>
using namespace std;
int valuered(int &v) // pass by reference is needed to use the modified value in main function.
{
v-=30;
return v;
}
int main()
{
int number=100;
valuered(number);
cout<<number;
}
Related
am a c++ beginner and this code really confused me:
int global = 100;
int& setGlobal()
{
return global;
}
int &a=setGlobal() ;
int main(void){
a=a+5;
std::cout<<global<<std::endl;
}
The return type of setGlobal is int& , but global is an int.
Please explain to me how does that work?
Shouldn't it be return &global ?
The code that i understand is like this:
int global = 100;
int& x=global;
int& setGlobal()
{
x+10;
return x;
}
int main(void){
x=x+10;
std::cout<<global<<std::endl;
}
Maybe my problem is with references.
A return type of T& gets you the reference of the returned object of type T.
In your case
int& setGlobal()
{
return global;
}
returns a reference (int&) to global. Basically an alias, another way to access the same variable.
This means that
int &a=setGlobal() ;
Sets a as a reference to global and any operation on a is reflected on global.
It should come as no surprise that
int main(void){
a=a+5;
std::cout<<global<<std::endl;
}
prints 105. a and global are effectively interchangeable in your main scope (because one is an alias of the other).
If setGlobal returned &global, it would be returning the address of global. The address is the actual location of the variable in memory, it's not an alias. If you wanted to work with pointers, your code would look like this instead:
#include <iostream>
int global = 100;
int* setGlobal()
{
return &global;
}
int* a=setGlobal() ;
int main(void){
*a=*a+5;
std::cout<<global<<std::endl;
}
Notice how we can't access the contents of global using a directly (it's just an address). We must first dereference it.
And for good measure, you should also know that, since setGlobal() returns a reference to global in your example, it can be used directly as an lvalue to access global like so:
setGlobal() += 5;
Putting the above statement just before printing will result in "110" being displayed. Fun stuff! I invite you to read about lvalues and rvalues on your own time as a next step in your C++ journey!
In my program (this is only a short version), I have a struct that has 9 members (airplanes) which all have the same variables.
struct FlightP {string FLID; int altitude; int heading; flightMode; } ArrP_1, ArrP_2;//1-9 etc
If I want to change for example the altitude of members ArrP_1 and ArrP_2 I did it like so:
int main(){
ArrP_1.altitude = 10000;
ArrP_2.altitude = 10000;
}
But is there a way to use a function like that:
void ALtChange(FlightP flight_p){
flight_p.altitude = 12000;
}
int main(){
ALtChange(ArrP_1);
ALtChange(ArrP_2);
//If I have to change multiple parameters in multiple members at the same time this function would make things easier.
}
Somewhy this function doesn't do anything. Is the function wrong or what should I do differently?
Somewhy this function doesn't do anything.
Your function modifies the function argument that is local to the function.
In order to modify a variable from another scope, you can use indirection: Use a reference argument.
Instead of modiying the object in the function, another approach is to write a function that returns a ALtChange object, and you can assign the result to a variable to modify it.
It's like #Jonnhy Mopp said, pass it by reference like so:
#include <iostream>
#include <string>
using namespace std;
struct FlightP {string FLID; int altitude; int heading; int flightMode; } ArrP_1, ArrP_2;//1
void ALtChange(FlightP& flight_p) { flight_p.altitude = 12000; }
void print_altitude(const FlightP& flight) { std::cout << flight.altitude << std::endl; }
int main(){
ArrP_1.altitude = 10000;
ArrP_2.altitude = 10000;
ALtChange(ArrP_1);
ALtChange(ArrP_2);
print_altitude(ArrP_1);
print_altitude(ArrP_2);
}
In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?
When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().
The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.
The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}
I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.
AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected
This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}
Digging through MSDN, I ran into just another curious line:
// This function returns the constant string "fourth".
const string fourth() { return string("fourth"); }
The full example is buried here: https://msdn.microsoft.com/en-us/library/dd293668.aspx Refined to bare minimum, it looks like this:
#include <iostream>
const int f() { return 0; }
int main() {
std::cout << f() << std::endl;
return 0;
}
A few other tests with different return types demonstrated that both Visual Studio and g++ compile lines like this without a warning, yet const qualifier seems to have no effect on what I can do with the result. Can anyone provide an example of where it matters?
you can not modify the returned object
example:
#include <string>
using namespace std;
const string foo(){return "123";}
string bar(){return "123";}
int main(){
//foo().append("123"); //fail
bar().append("123"); //fine
}
This is almost the same as const variable
#include <string>
using namespace std;
const string foo = "123";
string bar = "123";
int main(){
//foo.append("123"); //fail
bar.append("123"); //fine
}
It is part of the return type. The functions return const string and const int.
In the case of const int, this indeed makes no difference compared to int, because the only thing you can do with an int return value is to copy the value somewhere (in fact, the standard explicitly says that const has no effect here).
In the case of const string, it does make a difference, because a return value of class type can have member functions called on it:
fourth().erase(1);
will fail to compile in the case that fourth() returns a const string, because erase() is not a const method (it tries to modify the string it is called on).
Personally, I never make value-returning functions return a const value, as it unnecessarily constrains the caller (although some people feel that it is useful to prevent writing things like string s = fourth().erase(1);).
So I'm still rather new to programming/C++, and still trying to wrap my head around pointers and passing by reference and everything. A program I'm trying to figure out now needs to pass an array of structs to another function. I've gotten it working by just passing the array directly there. It seems to work fine. However, what I'm concerned about is that I believe I'm passing it by value, and I understand that it's better to pass structs by reference, so you're not making a copy of the struct every time...
Anyway, here's a basic example of what I'm doing:
struct GoldenHelmet {
int foo;
string bar;
};
void pass (GoldenHelmet ofMambrino[], int size);
int main () {
GoldenHelmet ofMambrino[10];
int size = sizeof(ofMambrino) / sizeof(ofMambrino[0]);
ofMambrino[1].foo = 1;
pass(ofMambrino, size);
cout << ofMambrino[2].foo << endl;
return 0;
}
void pass (GoldenHelmet ofMambrino[], int size) {
ofMambrino[2].foo = 100;
ofMambrino[2].bar = "Blargh";
}
From what I understand, it works because arrays are already pointers, right? But the way I have that configured, am I still passing a copy of the struct and everything to the pass() function? I've tried to pass it by reference, but it doesn't seem to want to work any way I've tried.
The C++ way:
#include <array>
typedef std::array<GoldenHelmet, 10> Helmets;
void pass(Helmets &);
int main()
{
Helmets h;
h[1].foo = 1;
pass(h);
//...
}
void pass(Helmets & h)
{
h[2].foo = 100;
// ...
}
Indeed, we pass the array by reference.
This syntax:
void pass (GoldenHelmet ofMambrino[], int size)
is actually quite confusing. Because you are not passing an array, you are passing a pointer. They are not the same thing though, don't get confused. This oddity only applies to function parameters. The above is exactly identical to this:
void pass (GoldenHelmet * ofMambrino, int size)
It's actually impossible to pass an array by value, unless it is a sub-object of another object. You can pass them by reference, you need to include the size though, but you can do that using a template:
template<int N>
void pass (GoldenHelmet (&ofMambrino)[N])
These are all possible, but none of them are pass by value. Just think of ofMambrino as being the address of the beginning of the array, and that is what you are passing.
void pass (GoldenHelmet ofMambrino[], int size)
void pass (GoldenHelmet ofMambrino[10], int size)
void pass (GoldenHelmet *ofMambrino, int size)
void pass (GoldenHelmet (&ofMambrino)[10], int size)
Arrays are represented and passed as pointers, so you are not copying anything here. In contrast, if you were passing a single struct, it would be passed by value.
Below is a code snippet to illustrate this last point:
void passByVal (GoldenHelmet ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
void passByRef (GoldenHelmet& ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
int main() {
GoldenHelmet h;
passByVal(h); // h does not change
passByRef(h); // fields of h get assigned in the call
}
First of all array is not pointers. We refer this as a pointer in the argument list because when we use
int x[ ]
x is actually const pointer that points the beginning of the array. And when you pass this to a function you send the adress of the memory that is beginning of the array. Thats why when you make a change in your function, you make change in the adress of your variable in the caller section actually. This is actualy simulated call by reference not call by reference. But effect is same with call by reference because you are working on memory locations. For this reason when you send array of your struct you pass actually adress of your array of structs. Thats why when you change value on this, you actually change your structs.
To use call by reference, one thing you must to do is to define your function prototype like
void f(int ¶m)
and when calling function, it is same with the others.
To summarize:
int main()
{
int x;
// simulated call by reference that use adress of variable,
// lets say adress of x is 19ff
f(&x); // actually you send 19ff
f(x); // call by reference that use reference of variable
}
// simulated call by reference
void f(const int *y)
{
// when you use like *y=10, you are writing on memory area 19ff, you actually
// change memory area that is belong to x in the main
}
// call by reference
void f(const int &y)
{
}