could not convert from 'unsigned int' to 'unsigned int&' - c++

I'm creating a method and one parameter of that method asks for a reference of an unsigned int, but I want to put a default value on that parameter. For example:
#include <iostream>
using namespace std;
class A {
public:
void sender();
private:
unsigned int score = 10;
};
class B {
public:
void receiver(unsigned int & score);
};
void A::sender() {
cout << "Before: " << score << endl;
B b;
b.receiver(score);
cout << "After: " << score << endl;
}
void B::receiver(unsigned int & score) {
score = 100;
}
int main() {
A a;
a.sender();
return 0;
}
Live demo: in here
The error happen when I do this:
void receiver(unsigned int & score = 10u);
And the compiler returns:
error: could not convert ‘10u’ from ‘unsigned int’ to ‘unsigned int&’
Live demo: in here

You cannot assign a literal1 to a non-const reference.
There are two scenarios where one will suit your situation:
You intend to modify the argument being passed to receiver()
If that is the case, the use a non-const reference (unsigned int & score) without the default parameter. In situations where you pass a literal or temporary object to it, then it will result in a compiler error.
a.receiver(10); // Error
The above wouldn't make any much sense considering that you want to modify that argument (you wouldn't see the modification if C++ had allowed that2).
You intend to just use the parameter in a read-only fashion
Just use plain, non-reference, unsigned int, because const unsigned int& score is just a pain to write. In cases where you determine that an object is expensive to copy, then that is the time where you should have the parameter a const reference.
UPDATE: There are some cases where you want to modify something, but that something may or may not exist. In cases like that, you may want to use a non-owning pointer as the parameter.
// Declaration
void receiver(unsigned int* score = nullptr);
void B::receiver(unsigned int* score) {
if(score) *score = 100;
}
...
a.receiver(); // Uses the default parameter
unsigned int x;
a.reciever(&x);
In this case, it only assigns to score when it points to some (assumed) valid variable. Pointers aren't that bad at all.
UPDATE 2: However, as #Potatoswatter have pointed out, you may be better off with function overloading.
void B::receiver() {
// Do something else
}
void B::receiver(unsigned int& score) {
score = 100;
}
You should use this in cases where you want your overloads to behave differently on different parameters.
However again, I prefer the first, non-default parameter option, rather than the pointer option and the overloading option, as it requires that the caller provide a parameter, which is much better when you are modifying something through a function.
UPDATE 3: You should also consider to have your function return the value instead of modifying it through a parameter. In cases where you don't need the current state of the object being modified, having a function return a value is much more intuitive. One caveat though is that the caller may forget to capture (assign) the return value, which could be dangerous if you are using that value as some resource ID to free something up.
1 And in general, a temporary object.
2 And the universe would probably blow up if 10 was magically transformed into 100 ;)

You want the argument type to be const unsigned int&. Otherwise, you can do something crazy, like try to assign 10 = 20, which doesn't make sense.
And that happens to be exactly that you did. The score = 100 line doesn't seem to be what you actually meant.

the value "10" isn't a reference- it's a value. By having a by-reference parameter, it must be called with a reference. Using a default parameter means you could call the function without specifying the parameter and the compiler would use the default.
Similarly, calling b.receiver(10); is not valid, but
int someInt = 10;
b.receiver(someInt);
is valid.

Related

C++ what is the point of "const" keyword? [duplicate]

This question already has answers here:
Sell me const-correctness
(16 answers)
Closed 2 years ago.
What is the point of using the keyword const? for example when making a game, one of the first things to do is to set the width and height of it. And most of the time you'll use for example:
const int Width
and
const int height
Now I know that you should do it like that because the width and height of the screen will not change throughout the game, but what is the point of doing so ? you can do the same thing without using const and it will work just fine.
That was just an example. so what I'm confused about right now is:
What is the point of using the const keyword anywhere if you won't change the variable anyway?
Non-exhaustive list of reasons:
Software Engineering (SWE). SWE is not just programming, but programming with other people and over time.
const allows to explicitly express an invariant, which lets you and others reason about the code. As the program becomes bigger, these invariants cannot be just memorized. That's why encoding them in the programming language helps.
Optimization opportunities.
With the knowledge that certain values will not change, the compiler can make optimizations that would not be possible otherwise. To take this to the max, constexpr means that a value will be known at compile time, not just at run-time. This becomes even more important in potentially multi-threading contexts.
Example:
What kind of optimization does const offer in C/C++?
I leave out whole program analysis which would require a much longer answer and almost certainly is not applicable to generic C++ programs. But whole-program-analysis will allow reasoning of the analyzer or compiler about constness of variables as they get passed between functions, translation units and libraries.
Without const, you have to remember to not change the variable. The larger your program becomes, the harder it gets.
It also has some other useful effects:
const int a = 10;
int b[a]; // Doesn't work if `a` is not `const`.
// ...
void foo(const int &a) {};
void bar()
{
foo(42); // Doesn't work if the parameter is a non-const reference.
}
Having something declared const, compared to a value set with #define for instance, allows you to declare something that the compiler will never let you alter, but that will still keep all of the other properties of a regular variable.
In particular, it will keep a certain place in memory and a pointer on it can be obtained with « & », keeping all read-only routines that use to work on regular object compatible with it.
It's especially useful when your constant object is not a simple native type variable, but rather a complicated object spawned from a class and that still need to be initialized through a constructor.
Also remember that const is a type qualifier, than can apply not only on variable declarations, but also on arguments of a function prototype. In this particular case, this will enable your function to accept both constant or variable arguments.
Such a constant argument could be, for example, a double-quoted "string", which is const char *-typed, because the string is directly part of the code itself and defined at compilation type. Without a const qualifier, nothing could prevent your function from trying to write in it, nor warn the programmer that it's forbidden.
To stay with your example, suppose I write a game library that has a
struct game {
int width;
int height;
int area;
game(int w, int h) : width(w),height(h),area(w*h) {}
};
Now you use my library and because I did not write any documentation (evil me) you just start writing code and try what you can do with that class. You write code
#include <iostream>
int main() {
game g{3,5};
g.width = 12;
std::cout << g.width << " * " << g.height << " == " << g.area;
}
and get output:
12 * 5 == 15
You will complain that the code I wrote is broken because you get non-sense results when you use it. If however I had used const for things you are not supposed to modify:
struct game {
const int width;
const int height;
const int area;
game(int w, int h) : width(w),height(h),area(w*h) {}
};
Then you would get a nice error message that tells you that you tried to modify something that you are not supposed to modify:
prog.cc: In function 'int main()':
prog.cc:11:15: error: assignment of read-only member 'game::width'
g.width = 12;
Once you fixed your code to
#include <iostream>
int main() {
game g{3,5};
std::cout << g.width << " * " << g.height << " == " << g.area;
}
All const could be removed and the output would not change. However this is not always the case. For example member functions can have const and non-const overloads that can do different things depending on whether the method is called on a const or on a non-const object:
#include <iostream>
struct foo {
void sayHello() const {
std::cout << "I am a const object\n";
}
void sayHello() {
std::cout << "I am a non-const object\n";
}
};
int main() {
const foo f;
f.sayHello();
foo g;
g.sayHello();
}
output:
I am a const object
I am a non-const object
Conclusion:
const is mainly to ensure correctnes and to avoid mistakes. const can also be used to make const objects behave differently than non const objects. There is more to it and details you can read up eg here.
const is for a constant variable, that it means nobody should change it, or maybe for const T & passing non-trivial type as parameter, or maybe for making a pointer constant, or for value pointed from the pointer (const *P *variable)

Looking for an explanation on why this C++ code does not work without references

I'm a beginner learning C++ and reached a chapter regarding passing arguments by references. There was a swap function defined as such:
void swap(double& d1, double& d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
The test was this, and it worked, with values swapped:
int main()
{
double x = 1;
double y = 2;
cout << "X==" << x << "y==" << y << '\n';
swap(x,y);
cout << "x==" << x << "y==" << y << '\n';
}
However I can't for the life of me figure out why removing the references makes this code do nothing:
void swap(double d1, double d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
I've done this since I wanted to better understand references since properly understanding them eludes me. I would appreciate an answer or a pointer in the right direction.
There are common notions in procedural programming languages like C++ of "pass by value" and "pass by reference".
When a variable is passed by value into a procedure (or function) a copy is made of the variable and any modifications made in the procedure (or function) don't reflect in the variable passed by value.
Conversely, when a variable is passed by reference modifications are reflected in the variable that was passed by reference.
The term reference in C++ refers to that idea so in the reference case the actions of swap() do swap the original variables passed as arguments, in the second case they don't.
If you see a function void foo(int x) called as foo(b); you should read that as "make a copy of b and perform foo on that copy".
If it were void foo(int &x) it would be "perform foo directly on b.
Lets use an analogy... you have a piece of paper with two numbers written on it. Now you want a friend to swap the two values. This:
void swap(double d1, double d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
is like you take a second piece of paper, write the numbers on it, give it to your friend (pass-by-value), he swaps the value but returns nothing to you (void return type). Will that change change the numbers on your piece of paper? No.
Lets change the strategy: Instead of giving your friend a copy of your numbers, you now tell him where he can find your piece of paper so he can do the job directly on that (pass-by-reference):
void swap(double& d1, double& d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
He still does not have to return anything to you, because once he is done you just have to look at your piece of paper to see the values swapped.
PS: analogies always have their limit, so take it with a grain of salt.
Passing a reference is like passing "the thing itself", not just its value.
It works kind of like if you handed a friend your precious ring, let them muck around with it in whatever way, and then got it back.
Passing by value is like handing a friend a different ring that looks exactly like your precious ring and they get to keep it, and you keep yours, untouched by their filthy, thieving fingerses.
A simpler example than swap:
void fv(int x)
{
x = 0;
}
If you pass a variable to this, that variable's value is copied into the completely indepent variable x.
x will have the same value as your variable, but it will not be the same thing.
When you assign a value to x, you're assigning to this variable, not to the one whose value was copied into it.
void fr(int& x)
{
x = 0;
}
If you pass a variable to this - fr(v) - x is your variable; the names "x" and "v" refer to the same thing.
Assigning a value to x inside the function is exactly the same as assigning a value to v in the calling code.
In the first example, you are passing the doubles as reference. Altering the values inside the function, changes the double x & y in your main.
In the second example, you are passing the doubles as value. This means, their value is copied ie. two new doubles are created and passed to the function. By changing those values, you modify the copied doubles - and not x & y from your main.
Because by default, when you pass a variable as a function argument, it's passed by value. That means that (like in a code below) when passed to the function, it actually creates a copy of it and you no longer work with the original variable and you operate with its copy - it has the same value but different location in memory.
int myVar = 10;
void f(int var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 10
Passing variable by its reference is there exactly because of the example you showed. You want to create a function that can actually modify the value of a passed variable outside of the scope of the function.
int myVar = 10;
void f(int& var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 20
You can think of it as a definition
I want to pass the variable to a function and I don't want it to change its value outside the function - use raw type - pass it by value
I want to pass the variable to a function and I want it to change its value outside the function - use & - pass it by reference
This is very often used when working with strings. For example: let's assume you get packet data in a variable std::string packet and you want to create a function that analysis it. You can do something like this
std::string packet;
someResultType func(std::string packet) {
....
}
auto result = function(packet);
But in this example, it is totally useless to create a new copy of variable packet because when working with it, you probably won't modify it, so you say to the compiler - I promise I won't modify the value thus you can pass the value by reference:
std::string packet;
someResultType func(const std::string& packet) {
// you're working with the global packet but you cant modify it
}
auto result = function(packet);

How is C++ function's default parameter passed?

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.

Tutorial c++ reference parameters issue

I have some doubts about C++ reference parameters. I am learning from this website:
http://www.doc.ic.ac.uk/~wjk/c++Intro/RobMillerL3.html
First program:
#include<iostream>
using namespace std;
int area(int length, int width);
int main()
{
int this_length, this_width;
cout << "Enter the length: ";
cin >> this_length;
cout << "Enter the width: ";
cin >> this_width;
cout << "\n";
cout << "The area of a " << this_length << "x" << this_width;
cout << " rectangle is " << area(this_length, this_width) << endl;
return 0;
}
int area(int length, int width)
{
int number;
number = length * width
return number;
}
Then the author suggests that "under some circumstances, it is legitimate to require a function to modify the value of an actual parameter that it is passed".After that he introduces new function:
void get_dimensions(int& length, int& width)
{
cout << "Enter the length: ";
cin >> length;
cout << "Enter the width: ";
cin >> width;
cout << "\n";
}
What is the main advantage when we pass values as parameters?
Advantages of passing by reference:
It allows us to have the function change the value of the argument, which is sometimes useful.
Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
We can pass by const reference to avoid unintentional changes.
We can return multiple values from a function.
Disadvantages of passing by reference:
Because a non-const reference can not be made to a literal or an expression, reference arguments must be normal variables.
It can be hard to tell whether a parameter passed by reference is meant to be input, output, or both.
It’s impossible to tell from the function call that the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
Because references are typically implemented by C++ using pointers, and dereferencing a pointer is slower than accessing it directly, accessing values passed by reference is slower than accessing values passed by value.
Sources:
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
http://www.functionx.com/cppcli/functions/Lesson10b.htm
https://en.wikibooks.org/wiki/C++_Programming/Code/Statements/Functions
There is already a good answer (imho worth accepting). However, I would like to give a more basic answer, as it seems like you encountered passing by reference for the first time:
This function:
void foo(int x){x +=1;}
can do anything with the value of the passed (by value) parameter, but it has no chance to return anything to the caller, i.e. the x+=1 has practically no effect at all.
On the other hand, this function:
void bar(int& x){x +=1;}
gets not only the value, but it is working on the actual variable that you pass as parameter (by reference). Thus the x+=1 has an effect also outside of the function.
Both functions in action:
int main(){
int a = 1;
foo(a); // foo gets a copy of a and increments its value
// a is still 1
bar(a); // bar directly increments the value of a
// a is now 2
}
This is the main difference of passing a parameters by reference (bar) vs passing by value (foo). The main advantage of passing by reference is that the value of the parameter needs not to be copied. (This is whypassing by value is usually done with a const reference. Passing a const reference is like passing the value because the value cannot be changed even if actually a reference is passed.) However, for more details I refer to Rohits answer.
int &a is a reference to any parameter passed to that function, You should always think of references as Alias to a variable (it is similar to a const pointer).
If your reference is not const you are allowed to changed and therefore change the content of the original variable.
It is useful for many reason first of all it can improve performances by avoiding doing copies when passing a parameter by reference, and it is also useful if you have a function that your expecting to return multiple results for example =:
int f (int &a,int &b,int &c,int&d);
int main
{
int first,second,third,result;
result = f(first,third,result);
}
All your int variables can be change within you function.

Returning function parameter, possible, bad style?

So I just had a thought, is it possible to return a parameter sent when a function is called. And if it is, is this considered fine or is it bad style?
Example:
int main()
{
...
int value = 1;
value = Foo(value);
...
}
int Foo(int i)
{
i = i * 2;
return (i);
}
As the parameter is being passed in and returned by value, this is fine - there is an implicit copy occurring when you call the function and when it returns.
For example
int value=1,other=0;
other=Foo(value);
other is now 2, value will still be 1
If you were passing in a reference or pointer then you would potentially run risks.
e.g. if the signature of Foo was
int Foo( int &i )
Then after the code chunk I used above, both other and value would be 2
There's no problem with "returning a parameter" in your example. You are not really "returning a parameter" at all. You are simply using the parameter in the argument expression of return. It is the result of that expression (the value of i) that gets returned, not the parameter itself.
One can argue that the "undesirable" property of your code sample is the fact that you are modifying the parameter inside the function, i.e. you are using the parameter as an ordinary local variable. There's nothing formally wrong with it, but sometimes people prefer to preserve the original parameter values throughout the function body. I.e. from that point of view your function would look better as
int Foo(int i)
{
return i * 2;
}
or as
int Foo(int i)
{
int i2 = i * 2;
return i2;
}
but, again, it is not really about "not returning a parameter", but rather about leaving the original value of i untouched inside the function.
There's no problem with doing that and it makes it very clear what's going on.
That's one valid approach to do this, but you might also like the idea of passing by reference:
int main()
{
...
int value = 1;
Foo(value);
...
}
void Foo(int &i)
{
i = i * 2;
}
The drawback to this approach is that you have to pass what's called an lvalue into the function-- basically, something that can be on the left side of an assignment statement, which here means a variable. A call with a literal or temporary, such as Foo(2), will fail to compile. The way you had written it originally will instead do an implicit copy by value into the local scope of the Foo function. Note that the return value is now also void.
Technically, there is no problem, but semantically, it is not advisable: in most cases the input of the function and the return value of the function are not the same, so you are reusing the variable to mean something different. It is clearer in next example
int main()
{
double i = 5;
i = getSquareSurface(i); // i was a length and is now a surface
}
This should be:
int main()
{
double length = 5;
double surface = getSquareSurface(length);
}
Of course, there are cases like the addOne() or in this case the Foo() function where the meaning doesn't change.