Please tell me the use of cascading, and when to use & before function like this int &func()
Where should i use that please give me small example, Thanks. I think it does return an address but no idea how to use.
You are about to commit a very common newbie mistake in C++, namely returning references to dead objects.
int &GetNumber()
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Looks innocent but will create so-called undefined behaviour. This means that the program may do whatever it wants to - it will likely crash, or it will sometimes crash. In any case, it won't be safe. Your compiler may even warn you if you attempt to do this. The reason is that by the time GetNumber has finished, the local number is destroyed, and you end up with a reference to a destroyed object.
Usually, you will want to return a copy instead of a reference. This is the "normal" thing to do in C++:
int GetNumber() // now OK
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Returning references is only safe when you know that the object referred to will continue to exist after the function returns. One example is when you are just returning a reference you were passed:
int &MyFunction(int &number)
{
// do something
return number;
}
This then allows you to chain functions:
struct Example
{
Example &MyFunction(Example &example)
{
// do something
return example;
}
};
int main()
{
Example example;
example.MyFunction(example).MyFunction(example).MyFunction(example);
}
Now, if this example strikes you as particularly useless (as it should), look at how the standard library handles << calls with std::ostream for a realistic use case.
std::cout << 1 << "a" << 0.5;
This syntax works because each operator<< call returns a reference to std::cout.
when to use &
Return by value vs return by reference
You usually return a reference when you want a caller to be able to change the original variable. Example can be returning elements of an array
struct Array
{
int values[ 10];
};
// Returns a reference to the nIndex element of rArray
int& Value( Array &rArray, int nIndex)
{
return Array.values[ nIndex];
}
int main()
{
Array myArray;
// Set the 10th element of sMyArray to the value 5
Value( myArray, 10) = 5;
assert( myArray.values[ 10] == 5); // OK
return 0;
}
Another example is returning reference to class member. You want to return original variable, not a copy of it. Consider:
struct A {
int something;
int f() { return something; }
int& g() { return something; }
};
int main()
{
A myA;
int i = myA.f(); // return by value: not original
// int but its copy with same value
i = 200;
assert( myA.something == 200); // fail
return 0;
}
but:
int main()
{
A myA;
int& i = myA.g(); // return by reference: original
// variable is referenced by i now
i = 200;
assert( myA.something == 200); // OK
return 0;
}
Operator chaining
Operator chaining is made to allow for expressions like:
a = b + c + d;
or
std::cout << "this" << " and " << "this";
Usually there is choice between returning by value or by reference made by considering the meaning of the operator or independent factors like for example that std::istream and std::ostream are not copyable, so trying to return objects of those types by value is an error.
Related
For example, if I have global variables:
int a;
int b;
I define that I can return a struct, I hope the members of the structure are bound to the global variables, and my modification to the members of the structure is to modify the global a, b. The code like:
struct bind
{
int a;
int b;
}
Bind getBind()
{
Bind bind;
band to a; // could be other variable, e.g. c
band to b; // could be other variable, e.g. d
return bind;
}
Note that it is not a simple reference, I may want to return the struct bound to c,d the next time I invoke getBind().
Background introduction:
collect data scattered around as a struct in a caller-unaware
way.
can return a const struct, caller can't modify its member
avoid modify member inconsciently by copy obj
I'm very puzzled, for the underlying language of C++, this should be easy to implement, but there seems to be no such funcation. Maybe I don't know, I hope so and get the answer here.
You can use references:
#include <iostream>
int a,b,c,d;
struct Bind {
int& ref1;
int& ref2;
};
Bind getBind(bool flag){
if (flag) return {a,b};
else return {c,d};
}
// ... or ...
Bind getBind(int& a,int& b){
return {a,b};
}
int main() {
auto x = getBind(true);
x.ref1 = 42;
x.ref2 = 101;
auto y = getBind(false);
y.ref1 = 0;
y.ref2 = 1;
auto z = getBind(a,b);
std::cout << z.ref1 << " " << z.ref2 << "\n";
auto w = getBind(c,d);
std::cout << w.ref1 << " " << w.ref2 << "\n";
}
Output:
42 101
0 1
However, it is not quite clear what you want to achieve. Global variables are better to be avoided in the first place and using reference as memebrs has certain implications, though if thats what you want then maybe its just fine.
I'm trying to write an example code for the following line of code:
int (*(*foo)(const void*))[3];
I got this code from here (at each refresh of the website you get a different piece of code and there is a finite set of them so by reloading a couple of times you will get my example). I wanted to see out of curiosity is it even possible to write some code that would make this line work.
Here is what I wrote so far:
#include<stdio.h>
#include<malloc.h>
int* goo(const void * ptr) {
int* ret = (int*) malloc(sizeof(int) * 3);
if (!ret)
return NULL;
for (int i = 0; i < 3; ++i)
ret[i] = i;
return ret;
}
int doo() { return 0; }
int main(void) {
//NOTE: Following 2 lines have syntax errors
int (*(*foo)(const void*))[3] = &goo;
int* values = foo(goo(doo));
for (int i = 0; i < 3; ++i) {
printf("%d", values[i]);
}
free(values);
return 0;
}
If I understood correctly, foo should be some function that receives as an argument another function and returns an int array of size 3. The problem is I don't know how to make foo in this case point to a function or even how to get the int array.
Is it even possible to make this line of code work?
If I understood correctly, foo should be some function
foo is a pointer to a function.
that receives as an argument another function
No, the parameter type of the function that foo points to must be a pointer to const void i.e. const void*. A pointer to void is an object pointer. It can point to an object of any type.
Functions are not objects, but on some systems, pointers to functions can be reinterpreted as pointers to void.
and returns an int array of size 3.
No; Return types cannot be arrays. The function must return a pointer to an array of 3 ints i.e. int(*)[3].
Is it even possible to make this line of code work?
Here is an example program that uses such foo. It doesn't make much sense, but that's because the goal is to use an obscure function pointer:
#include<iostream>
int arr[] {
1,
2,
3,
};
int (*goo(const void*))[3] {
return &arr;
}
int main() {
int (*(*foo)(const void*))[3] = &goo;
int (*values)[3] = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
We can greatly improve readability by introducing type aliases:
using IntArr3 = int[3];
using FooFun = IntArr3*(const void*);
IntArr3* goo(const void*) {
return &arr;
}
int main() {
FooFun* foo = &goo;
IntArr3* values = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
I've been trying to understand rvalues, lvalues and references and their usage as a returning values of functions (methods) so i created few small examples for practice purpose.
So firstly, i came up with this code (after reading somewhere, possibly here, that whenever i have a "regular" (without reference) return value for some method, it is considered to be rvalue, exception is when i add reference operator sign in the return value, like in this example:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
References() = 3;
std::cout << x;
getchar();
getchar();
}
So here, function References returns lvalue when called, and this code works out just fine, however, since this works, i thought that i can do something similar other way around, and this is what i tried:
#include <iostream>
int x = 5;
int References()
{
return x;
}
int main()
{
int a = References();
std::cout << a;
getchar();
getchar();
}
This code works just fine, the output is 5, which means that i successfully assigned value to the variable a, which is something i expected since this function returns "ordinary" integer so it a rvalue.
HOWEVER,
when i once again add reference operator sign to the return value of function References, again, it works fine:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
int a = References();
std::cout << a;
getchar();
getchar();
}
So, even though my function now returns int& which is returned as lvalue, this code still works and the output is still 5, which means that i managed to assign the value to my variable a successfully. What is going on here? Any help appreciated!
When you return by reference you have an lvalue, when you return by value you have a prvalue. In your case the difference you can read from both of them, but cannot assign to prvalue, not clear where is your confusion coming from:
int i1 = lvalue; // fine
int i2 = prvalue; // fine
but:
lvalue = 123; // fine
prvalue = 123; // error
closer to your case:
int &func1();
int func2();
int i1 = func1(); // fine
int i2 = func2(); // fine
func1() = 123; // fine
func2() = 123; // error
more info: Value Category
When you use a reference in an expression or an assignment, it evaluates out to what the reference refers to, not the memory address, which I suppose is what you expect to see.
Compare the output of the following functions:
int x = 5;
int& Reference()
{
return x;
}
int *Pointer()
{
return &x;
}
int main()
{
std::cout << Reference() << std::endl;
std::cout << Pointer() << std::endl;
return 0;
}
According to https://learn.microsoft.com/en-us/previous-versions/f90831hc(v=vs.140) :
You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.
The third example is exactly the same as the second one, it's copying the value. You can copy a value from an lvalue just how you can copy a value from an rvalue. If your a variable was of type int& instead, you wouldn't be copying the actual value, you'd just get the same reference. This might help you understand:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
int a = References();
int& b = References();
std::cout << a; // 5
std::cout << b; // 5
std::cout << x; // 5
a = 6;
b = 7;
std::cout << a; // 6
std::cout << b; // 7
std::cout << b; // 7
getchar();
getchar();
}
For comparison:
int n = 10;
int& r = n;
int* p = &n;
int x = n; // copy by value
int y = r; // copy by value, too, use the variable referenced as source
int z = *p; // copy by value third time, using variable pointed to
int& r0 = r; // copy the reference, i. e. r0 now references n as well
int* p0 = p; // copy the pointer...
n = 12;
// now x, y, z all STILL have value 10!
// r, r0, *p and *p0, in contrast, all yield 12
Not different with functions:
int& ref() { return n; }
int val() { return n; }
int& r1 = ref(); // copy the reference, again r1 references n!
int& r2 = val(); // INVALID!!!
// the latter is comparable to:
int& r3 = 7; // invalid...
What's the difference in usage of function get1() and get2()?
struct x
{
float get1() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
float& get2() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
};
int main()
{
x t;
float x1 = t.get1();
float/*&*/ x2 = t.get2();
cout << x1 << endl;
cout << x2 << endl;
cin.get();
}
As i understand, get2() can only be const class member..
It's not clear for me completely. If someone can point me to a reference or just a short but complete solution, would be nice.
In your case, get2() invokes undefined behavior because you return a reference to a method-local that goes out of scope.
The difference is that returning float returns a float value, while float & returns a reference to a float. The reference can be used to alter the data of the referent; when returning by value you just get a copy.
It sounds like you are just confused about what references do, so here is the colloquial definition: a reference is another name for an object. That means that a reference requires the existence of its target to exist elsewhere, very similar to a (non-null) pointer.
Let me write a better example to illustrate the difference:
struct x
{
x() : data(0) { }
float get1() const
{
return data;
}
// Cannot be const now, because we can't return a non-const reference to what
// would be a const data member. (If this method were const then data would be a
// const float, and that cannot bind to float &.)
float & get2()
{
return data;
}
private:
float data;
};
Now we have two methods, one that returns data and one that returns a reference to it. The difference here is that with get2() you can actually change the value of x::data:
x an_x;
float a = an_x.get1(); // a is 0
a = 5; // a is 5, an_x.data is still 0
a = x.get1(); // a is 0 again, because an_x.data did not change
float & b = an_x.get2(); // b is 0
b = 5; // b is 5, and so is an_x.data!
a = x.get1(); // a is now 5, because an_x.data is 5
Notably, returning a reference makes the result of the expression an lvalue:
an_x.get1() = 5; // Compile-time error, because a float is not an lvalue.
an_x.get2() = 5; // Compiles, and sets an_x.data to 5.
This is a technique used by the standard library containers; vector<int> for example returns int & from its non-const operator[] overload, which is why some_vector[0] = 5; compiles and works as you would expect.
float fx = 4;
In your case fx is local variable. It will die once you come out of function. If you are returning float then you are making copy of value, so even fx die, no problem. But if you are returning float&, you are returning reference to died variable. Which is undefined behaviour.
Copying is costly operation. When you return reference, you are not making actual copy, but you are returning address of varaiable. You should return reference if your variable will alive after returning from function. But in your case, fx will die once you come out of function.
I simulated your case in below blocks of code, you can compare the output of two case for making clearly. Hope it help.
#include <iostream>
class A
{
public:
A()
{
std::cout << this << ": A()\n";
}
A(const A&)
{
std::cout << this << ": Copy constructor\n";
}
~A()
{
std::cout << this << ": ~A()\n";
}
};
struct x
{
A get1() const
{
A a;
return a;
}
A &get2() const
{
A a;
return a;
}
};
int main(int argc, char *argv[])
{
x t;
/*{
t.get1();
}*/
{
t.get2();
}
std::cin.get();
}
Just a tiny question:
Can you tell me what's the issue here in this code ? It should print out 9 but it does 4.8921e-270, however, when uncommenting line 4, it works just fine, too.
I don't understand what might be wrong here. Thank you !
Code:
double& foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
int main() {
cout << foo() << "\n";
}
Result:
4.8921e-270
It is a bad idea to return references/pointers to objects on the stack. They are likely destroyed when you leave the function. Try returning it as per value:
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Now the return value is copied instead of a reference to an object that is probably not existing anymore.
You are returning a reference to a local object, the object ceases to exist when foo completes, and then you get Undefined Behavior when you dereference it.
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Never a good idea to return references to objects on stack. Most likely they would be disappear when you leave the function. You might try returning it as per value.
You return a reference to a local variable - since the local variable goes out of scope as soon as foo() returns, the value no longer exists.
So you should either just change the return type to double (highly recommended) and return x or (if you absolutely want/have to return a reference) use a static variable instead:
double& foo() {
static double x = 9;
double &y = x;
return y;
}
I often return data members of a class by const ref:
class BigThing {...};
class Foo
{
public:
const BigThing & getBT() const { return bt; } // For constant BigThing.
BigThing & getBT() { return bt; } // For mutable BigThing.
private:
BigThing bt;
};
Then as long as your instance of Foo is in scope (you don't want to return a ref to a local variable) then using one of the getBT() should be safe and efficient.