C++ How works set of function's argument value? - c++

I am learning C++ and I have code:
float x, y;
namespace X {
void SetMyX(float p) {
x = p;
}
void SetMyY(float p) {
y = p;
}
namespace XY {
void Set(float p = 0.0f) {
x = p;
p = y;
}
}
}
int main() {
X::SetMyX(5.4f);
std::cout << "x = " << x << " y = " << y << std::endl;
X::SetMyY(4.1f);
std::cout << "x = " << x << " y = " << y << std::endl;
X::XY::Set();
std::cout << "x = " << x << " y = " << y << std::endl;
return 0;
}
And output is:
x = 5.4 y = 0
x = 5.4 y = 4.1
x = 0 y = 4.1
And I figure out variable p sets value of x and then y sets value of p? But, how it is possible? In C++ you can also set value of function's argument or what?
It's just weird for me because I thought you can't just "editing" entered value and you must add another variable like result or something like that, or just return sum of two arguments, but change them?

Yes, the argument p is a completely normal variable and you can do everything with it.
This will also work in many other languages like C, Java, Javascript or Python.

Related

Global and local variables in C++

I'm fairly new to C++, and I'm experiencing some issues when printing local and global variables. Consider this simple piece of code:
#include <cstdlib>
#include <iostream>
using namespace std;
/*
*
*/
int x = 10; // This x is global
int main() {
int n;
{ // The pair of braces introduces a scope
int m = 10; // The variable m is only accessible within the scope
cout << m << "\n";
int x = 25; // This local variable x hides the global x
int y = ::x; // y = 10, ::x refers to the global variable x
cout << "Global: " << y << "\n" << "Local: " << x << "\n";
{
int z = x; // z = 25; x is taken from the previous scope
int x = 28; // it hides local variable x = 25 above
int t = ::x; // t = 10, ::x refers to the global variable x
cout << "(in scope, before assignment) t = " << t << "\n";
t = x; // t = 38, treated as a local variableout was not declared in this scope
cout << "This is another hidden scope! \n";
cout << "z = " << z << "\n";
cout << "x = " << x << "\n";
cout << "(in scope, after re assignment) t = " << t << "\n";
}
int z = x; // z = 25, has the same scope as y
cout << "Same scope of y. Look at code! z = " << z;
}
//i = m; // Gives an error, since m is only accessible WITHIN the scope
int m = 20; // This is OK, since it defines a NEW VARIABLE m
cout << m;
return 0;
}
My goal is practicing the accessibility of the variables within the various scopes, and then printing them. However, I'm not able to figure out why when I try to print the last variable z, NetBeans gives me back the output 2025.
Here it follows my sample output:
10
Global: 10
Local: 25
(in scope, before assignment) t = 10
This is another hidden scope!
z = 25
x = 28
(in scope, after re assignment) t = 28
Same scope of y. Look at code! z = 2520
RUN FINISHED; exit value 0; real time: 0ms; user: 0ms; system: 0ms
Hope that somebody can help me understanding what is going on! :)
is not that z is holding the value 2520 is the fact that you ommit to add a new line operator between printing z and printing m...
you are doing:
cout << "Same scope of y. Look at code! z = " << z;
}
int m = 20;
cout << m;
but you should do:
std::cout << "Same scope of y. Look at code! z = " << z << std::endl;
}
int m = 20;
std::cout << m << std::endl;
if you just followed the same criteria of labeling the output and doing something like
std::cout << "M is: "<<m << std::endl;
you would spotted the issue faster by observing the output:
25M is: 20

c++ lambda capture by value

I am reading through the C++ lambda section in chapter 3 of this book and the following code confuses me:
int x = 0;
int y = 42;
auto qqq = [x, &y] {
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
This code prints out:
x: 0
y: 77
x: 0
y: 78
final y: 79
Why does qqq() not register that x has changed to 77? It was stated that passing by value means we can read but not modify data readable where the lambda was defined. Does that mean we can't see changes after it's definition?
That's because the variable is captured by value (i.e. copied) only once, when you define the lambda. It's not "updated" as you may believe. The code is roughly equivalent to:
#include <iostream>
int x = 0;
struct Lambda
{
int _internal_x; // this is used to "capture" x ONLY ONCE
Lambda(): _internal_x(x) {} // we "capture" it at construction, no updates after
void operator()() const
{
std::cout << _internal_x << std::endl;
}
} qqq;
int main()
{
qqq();
x = 77; // this has no effect on the internal state of the lambda
qqq();
}
Live on Coliru
By binding a variable by value to a lambda closure, you're effectively copying the value of the variable into a separate variable that is found inside the lambda object. Likewise, by binding a variable by reference, you're making such an internal variable to be a reference to the original variable instead, thus being able to "see changes" on the original variable.
Look at it like this. The following code...
#include <iostream>
int main()
{
int x = 0;
int y = 42;
auto qqq = [x, &y] {
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
}
Is (kind of, but not exactly) syntactic sugar for...
#include <iostream>
class MyLambda
{
private:
int x;
int& y;
public:
MyLambda(int x, int& y) : x(x), y(y) {}
void operator()()
{
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
}
};
int main()
{
int x = 0;
int y = 42;
MyLambda qqq = MyLambda(x, y);
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
}
With the exception of the special lambda syntax and the fact that you can't reference the lambda's type directly. By comparing the former with the later code, you should be able to clear out your understanding of closures.
The lambda uses the value at the time the lambda is defined (it makes a copy), not at the time it is invoked.
This might help: How are Lambda Closures Implemented?

On Pointers and Dereferencing

I've been working on learning C++ lately and picked up the book "C++ Through Game Programming". I'm on the chapter on Pointers and I've been presented an example that I have a question about. The code is this:
#include "stdafx.h"
#include <iostream>
using namespace std;
void badSwap(int x, int y);
void goodSwap(int* const pX, int* const pY);
int main()
{
int myScore = 150;
int yourScore = 1000;
cout << "Original values\n";
cout << "myScore: " << myScore << "\n";
cout << "yourScore: " << yourScore << "\n\n";
cout << "Calling badSwap()\n";
badSwap(myScore, yourScore);
cout << "myScore: " << myScore << "\n";
cout << "yourScore: " << yourScore << "\n\n";
cout << "Calling goodSwap()\n";
goodSwap(&myScore, &yourScore);
cout << "myScore: " << myScore << "\n";
cout << "yourScore: " << yourScore << "\n";
cin >> myScore;
return 0;
}
void badSwap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
void goodSwap(int* const pX, int* const pY)
{
//store value pointed to by pX in temp
int temp = *pX;
//store value pointed to by pY in address pointed to by pX
*pX = *pY;
//store value originally pointed to by pX in address pointed to by pY
*pY = temp;
}
In the goodSwap() function there's the line:
*pX = *pY;
Why would you dereference both sides of the assignment? Isn't that the equivalent of saying "1000 = 150"?
Why would you dereference both sides of the assignment? Isn't that the equivalent of saying "1000 = 150"?
No, just like the following:
int x = 1000;
int y = 150;
x = y;
is not the equivalent of saying "1000 = 150". You're assigning to the object, not to the value it presently contains.
The below is precisely the same (since the expression *px is an lvalue referring to the object x, and the expression *py is an lvalue referring to the object y; they're literally aliases, not some strange, disconnected version of the objects' numerical values):
int x = 1000;
int y = 150;
int* px = &x;
int* py = &y;
*px = *py;
*px=*py means we are assigning the value not address, from address of py to address of px.
Skip the chapter of the book or buy another one:
there is no need of using plain pointers in C++ nowadays.
Also there is a std::swap function, that does the things C++isch.

Variable changes value when passed to function?

I feel like an idiot. When I pass a variable to the function it results in a strange output like 6.2+e003 instead of the value that the variable holds. What am I doing wrong?
The x in main and the x in the function are different?
main:
int x, y;
while(system.WindowOpen())
{
x++;
y++;
bg.Draw2D();
bob.Think(x, y);
riley.Think(x, y);
system.Render(0);
}
class method:
void Organism::Think(double x, double y)
{
std::cout << "X: " << x << "\n";
std::vector<double> food;
food.push_back(x);
food.push_back(y);
std::cout << "VECTOR: " << food[0] << " " << food[1] << "\n";
std::vector<double> path;
if(refresh.IsTime()) {
std::cout << "\nFOOD VECTOR: \n" << food[0]
<< "\n" << food[1] << "\n";
path = brian.GetOutput(food);
organism.Translate2D(path[0], path[1]);
if(organism.IsOffScreen2D(resX, resY) == 'l' )
organism.SetPos2D(resX, organism.GetY());
if(organism.IsOffScreen2D(resX, resY) == 'r')
organism.SetPos2D(0, organism.GetY());
if(organism.IsOffScreen2D(resX, resY) == 't')
organism.SetPos2D(organism.GetX(), resY);
if(organism.IsOffScreen2D(resX, resY) == 'b')
organism.SetPos2D(organism.GetX(), 0);
};
font.DrawNumber2D(x, 50, 50);
font.DrawNumber2D(y, 50, 100);
organism.Draw2D();
}
Both x and y are uninitialized here:
int x, y;
so they can hold any value, and reading from them is undefined behaviour. You should initialize them:
int x = 0
int y = 0;
I was writing outside the bounds of a vector. I switched from using the [] operators to using the .at() and found my bug right away. Just a bit of memory corruption. I feel quite silly. Thanks all!

Why does changing what a reference points to not throw an error?

Iv got to the stage in my c++ study concerning references. It states the following rule:
Once a reference is initialized to an object, it cannot be changed to refer to another object.
Iv wrote a short code (as asked to in an exercise) that is meant to prove this rule correct.
int y = 7;
int z = 8;
int&r = y;
r = z;
Can someone explain why this code compiles without any errors or warnings?
r = z does not change what r "points to." It assigns the value of z to the object pointed to by r.
The following code does the same thing as your code, but using pointers instead of references:
int y = 7;
int z = 8;
int* p = &y; // p points to y
*p = z; // assign value of z to the object pointed to by p (which is y)
It does not make the reference alias to something else but it changes the value of what r contains.
int&r = y;
ris reference to y
r = z;
changes value of y & r to value of z by assigning value of z to r & hence y.
int&r = y;
r = z;
It does NOT change the reference. Rather it changes the value pointed to by the reference variable. The reference variable is just yet another name of y. So r=z is equivalent to
y = z;
That is, r=z changes the value of y.
Reference variable cannot be reset to refer to another variable, in any way.
You're not changing the reference; you're setting a new value to the referred object. After this example you should note that y==8.
When you do r = z you are not reseating the reference, instead you are copying the value of z into y.
I faced the same issue when study <<thinking in c++> charpter11.
here is my understanding code: the second compile error seems can not be simulated. but can understand. you can draw a picture to see what x, y, z, and ref2 point to.
/**
Write a program in which you try to
(1) Create a reference that is not initialized when it is created.
(2) Change a reference to refer to another object after it is initialized.
(3) Create a NULL reference.
**/
#include <iostream>
using namespace std;
int main() {
// 1
//int& ref1; // compile error:
int x = 10;
int& ref2 = x;
cout << "x = " << x << endl;
cout << "ref2 = " << ref2 << endl << endl;
// 2
int y = 20;
ref2 = y; // 这里没有编译错误,ref2的指向并未改变,其指向的空间由10改变为20
cout << "ref2 = " << ref2 << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl << endl;
int z = 30;
ref2 = z;
cout << "ref2 = " << ref2 << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "z = " << z << endl;
// 3
//int& ref3 = NULL; // compile error:
return 0;
}