difference between variable and reference assignment - c++

This has bothered me, I have just gotten back into c++ lately, and am well aware of references. Why does it seem there is no difference between b and c below. In other words, intuitively I would think c not being a ref variable would take a copy. It got me thinking when considering the problem of returning a reference to a local variable.
int a = 10;
int& func()
{
return a;
}
int &b = func();
int c = func(); // shouldn't this make a copy into c but c acts like a reference.

I would think c not being a ref variable would take a copy.
c is indeed a copy of a. Note that int c = func(); is copy initialization while int &b = func(); is reference initialization.
This means that if you make changes to c they will not be reflected on a. Demo
int a = 10;
int& func()
{
return a;
}
int &b = func(); //reference initialization
int c = func(); //copy initialization
int main()
{
c = 20;
std::cout << a<< " "<< b <<" "<< c <<std::endl; // 10 10 20
return 0;
}
Note also the emphasis on "initialization" instead of "assignment". These terms have different meaning in C++ unlike other languages(python for instance).

Thanks for the answers, makes sense now. This question started from "why can't I return a local variable reference to a variable if its a copy?" Well, I realized because its too late at that point - the stack is gone. I was thinking the copy could be made before the stack went away - wrong!
You can return to a reference but when you use it, segfault.
Return to a variable and, segfault immediately since it tries to copy.
int& func() // compile warning
{
int a = 10;
return a;
}
int &b = func(); // ok, but segfault if try to use b.
int c = func(); // segfault immediately

Related

How can a pointer to local scoped object still invoke the object method?

In my understanding that might be wrong, declaring a pointer to local object is dangerous or probably has no purpose.
The following globally defined function Factory that returns a pointer to a local object has no purpose. Right after invoking Factory(), the returned address is pointing to a local object that has been destroyed.
Foo* Factory()
{
// It is wrong to return the address of a local object!
// It is only for illustration!
Foo local{ 100 };
return &local;
}
Invoking Print() produces a garbage value. This is understandable so far.
Now consider the second case with a local scope as follows.
int main()
{
Foo* p ;
{
Foo local{ 100 };
p = &local;
}
p->Print();// 100 is printed even though p is pointing to a local scoped object that has been destroyed.
return 0;
}
What I don't understand is why I can still invoke Print() on the pointed object that should have been destroyed. Any comments are welcome!
Complete Example
#include <iostream>
class Foo
{
private:
int _data;
public:
Foo(int data) :_data{ data }
{
std::cout << "Ctor: " << this << std::endl;
}
~Foo()
{
std::cout << "Dtor: " << this << std::endl;
}
void Print()
{
std::cout << "Data: " << _data << std::endl;
}
};
Foo* Factory()
{
// It is wrong to return the address of a local object!
// It is only for illustration!
Foo local{ 100 };
return &local;
}
int main_1()
{
Foo* p = Factory();
p->Print();// Garbage gets printed because p is pointing to a local object that has been destroyed.
return 0;
}
int main_2()
{
Foo* p ;
{
Foo local{ 100 };
p = &local;
}
p->Print();// 100 is printed even though p is pointing to a local scoped object that has been destroyed.
return 0;
}
Undefined behavior
First I want to give you a brief explanation of undefined behavior. If you want to you can read more here Undefined behavior.
Undefinded behavior renders the entire program meaningless if certain rules of the language are violated. The compiler can basicly decide what to do. But like mentioned on cppreference: Compilers are not required to diagnose undefined behavior (although many simple situations are diagnosed), and the compiled program is not required to do anything meaningful. So in short there are no restrictions on the behavior of the program.
Your case
Both examples invoke undefned behavior:
int main_2()
{
Foo* p ;
{
Foo local{ 100 };
p = &local;
}
p->Print();
return 0;
}
int main_1()
{
Foo* p = Factory();
p->Print();
return 0;
}
So like we learned undefinded behavior is undefinded. So anything can happen. In the second case your compiler was probably smart enough to notice the issue.Because the behavior is undefined your program could also crash or do other weird things.

Reference return value and value updation in destructor

#include <iostream>
using namespace std;
int i; //1 - global
class Test
{
public:
~Test()
{
i = 10;
}
};
int& foo()
{
int i = 3; //2 - local
Test ob;
return i;
}
int main()
{
cout << "i = " << foo() << endl; // output: i = 3
return 0;
}
I have queries for above code:
Variable i being local to foo, reference of which cannot be used (automatic variable). How does above code execute?
The Test object in foo function will be destroyed after return statement. How does foo function returns reference of 2 (i = 3)?
Variable i being local to foo, reference of which cannot be used (automatic variable). How does above code execute?
What you are doing is cause for undefined behavior. Unfortunately, seemingly sane behavior falls under undefined behavior too. A legendary answer on SO expounds on the subject.
The Test object in foo function will be destroyed after return statement. How does foo function returns reference of 2 (i = 3)?
The first statement is correct. However, that is not relevant to the issue of which i is returned from foo. foo returns a reference to the function local variable regardless of what Test does.
You always read and wrote the global i since you never declared local i or class member i in your code.
when you call foo() like
cout << "i = " << foo() << endl;
This block of code will execute
int& foo() {
i = 3; //2 - local
Test ob; /* object having local scope */
return i;
}/* when it goes out of this block.. destructor gets called */
above you are creating object ob. when it came out of scope, destructor ~Test() { } gets called automatically & in destructor you have i=10, so return i; will return i value which was there in destructor. so it prints i value as 10. Also i = 3; doesn't create new i it will consider global declared i.
updated code :
int& foo() {
int i = 3; /* here i is locally created */
Test ob;
return i; /* you can't return reference to local variable.. invokes UB */
}
Above code block will cause undefined behavior.

Create and return a function within another function [duplicate]

I mean something like:
int main()
{
void a()
{
// code
}
a();
return 0;
}
Modern C++ - Yes with lambdas!
In current versions of c++ (C++11, C++14, and C++17), you can have functions inside functions in the form of a lambda:
int main() {
// This declares a lambda, which can be called just like a function
auto print_message = [](std::string message)
{
std::cout << message << "\n";
};
// Prints "Hello!" 10 times
for(int i = 0; i < 10; i++) {
print_message("Hello!");
}
}
Lambdas can also modify local variables through **capture-by-reference*. With capture-by-reference, the lambda has access to all local variables declared in the lambda's scope. It can modify and change them normally.
int main() {
int i = 0;
// Captures i by reference; increments it by one
auto addOne = [&] () {
i++;
};
while(i < 10) {
addOne(); //Add 1 to i
std::cout << i << "\n";
}
}
C++98 and C++03 - Not directly, but yes with static functions inside local classes
C++ doesn't support that directly.
That said, you can have local classes, and they can have functions (non-static or static), so you can get this to some extend, albeit it's a bit of a kludge:
int main() // it's int, dammit!
{
struct X { // struct's as good as class
static void a()
{
}
};
X::a();
return 0;
}
However, I'd question the praxis. Everyone knows (well, now that you do, anyway :)) C++ doesn't support local functions, so they are used to not having them. They are not used, however, to that kludge. I would spend quite a while on this code to make sure it's really only there to allow local functions. Not good.
For all intents and purposes, C++ supports this via lambdas:1
int main() {
auto f = []() { return 42; };
std::cout << "f() = " << f() << std::endl;
}
Here, f is a lambda object that acts as a local function in main. Captures can be specified to allow the function to access local objects.
Behind the scenes, f is a function object (i.e. an object of a type that provides an operator()). The function object type is created by the compiler based on the lambda.
1 since C++11
Local classes have already been mentioned, but here is a way to let them appear even more as local functions, using an operator() overload and an anonymous class:
int main() {
struct {
unsigned int operator() (unsigned int val) const {
return val<=1 ? 1 : val*(*this)(val-1);
}
} fac;
std::cout << fac(5) << '\n';
}
I don't advise on using this, it's just a funny trick (can do, but imho shouldn't).
2014 Update:
With the rise of C++11 a while back, you can now have local functions whose syntax is a little reminiscient of JavaScript:
auto fac = [] (unsigned int val) {
return val*42;
};
For a recursive function, compile-time type deduction is not supported:
function<int(int)> factorial{ [&](int n)
{
return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
} };
You can't have local functions in C++. However, C++11 has lambdas. Lambdas are basically variables that work like functions.
A lambda has the type std::function (actually that's not quite true, but in most cases you can suppose it is). To use this type, you need to #include <functional>. std::function is a template, taking as template argument the return type and the argument types, with the syntax std::function<ReturnType(ArgumentTypes)>. For example, std::function<int(std::string, float)> is a lambda returning an int and taking two arguments, one std::string and one float. The most common one is std::function<void()>, which returns nothing and takes no arguments.
Once a lambda is declared, it is called just like a normal function, using the syntax lambda(arguments).
To define a lambda, use the syntax [captures](arguments){code} (there are other ways of doing it, but I won't mention them here). arguments is what arguments the lambda takes, and code is the code that should be run when the lambda is called. Usually you put [=] or [&] as captures. [=] means that you capture all variables in the scope in which the value is defined by value, which means that they will keep the value that they had when the lambda was declared. [&] means that you capture all variables in the scope by reference, which means that they will always have their current value, but if they are erased from memory the program will crash. Here are some examples:
#include <functional>
#include <iostream>
int main(){
int x = 1;
std::function<void()> lambda1 = [=](){
std::cout << x << std::endl;
};
std::function<void()> lambda2 = [&](){
std::cout << x << std::endl;
};
x = 2;
lambda1(); //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
lambda2(); //Prints 2 since that's the current value of x and x was captured by reference with [&]
std::function<void()> lambda3 = [](){}, lambda4 = [](){}; //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
//[](){} is the empty lambda.
{
int y = 3; //y will be deleted from the memory at the end of this scope
lambda3 = [=](){
std::cout << y << endl;
};
lambda4 = [&](){
std::cout << y << endl;
};
}
lambda3(); //Prints 3, since that's the value y had when it was captured
lambda4(); //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
//This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
//This is why you should be careful when capturing by reference.
return 0;
}
You can also capture specific variables by specifying their names. Just specifying their name will capture them by value, specifying their name with a & before will capture them by reference. For example, [=, &foo] will capture all variables by value except foo which will be captured by reference, and [&, foo] will capture all variables by reference except foo which will be captured by value. You can also capture only specific variables, for example [&foo] will capture foo by reference and will capture no other variables. You can also capture no variables at all by using []. If you try to use a variable in a lambda that you didn't capture, it won't compile. Here is an example:
#include <functional>
int main(){
int x = 4, y = 5;
std::function<void(int)> myLambda = [y](int z){
int xSquare = x * x; //Compiler error because x wasn't captured
int ySquare = y * y; //OK because y was captured
int zSquare = z * z; //OK because z is an argument of the lambda
};
return 0;
}
You can't change the value of a variable that was captured by value inside a lambda (variables captured by value have a const type inside the lambda). To do so, you need to capture the variable by reference. Here is an exampmle:
#include <functional>
int main(){
int x = 3, y = 5;
std::function<void()> myLambda = [x, &y](){
x = 2; //Compiler error because x is captured by value and so it's of type const int inside the lambda
y = 2; //OK because y is captured by reference
};
x = 2; //This is of course OK because we're not inside the lambda
return 0;
}
Also, calling uninitialized lambdas is undefined behavior and will usually cause the program to crash. For example, never do this:
std::function<void()> lambda;
lambda(); //Undefined behavior because lambda is uninitialized
Examples
Here is the code for what you wanted to do in your question using lambdas:
#include <functional> //Don't forget this, otherwise you won't be able to use the std::function type
int main(){
std::function<void()> a = [](){
// code
}
a();
return 0;
}
Here is a more advanced example of a lambda:
#include <functional> //For std::function
#include <iostream> //For std::cout
int main(){
int x = 4;
std::function<float(int)> divideByX = [x](int y){
return (float)y / (float)x; //x is a captured variable, y is an argument
}
std::cout << divideByX(3) << std::endl; //Prints 0.75
return 0;
}
No.
What are you trying to do?
workaround:
int main(void)
{
struct foo
{
void operator()() { int a = 1; }
};
foo b;
b(); // call the operator()
}
Starting with C++ 11 you can use proper lambdas. See the other answers for more details.
Old answer: You can, sort-of, but you have to cheat and use a dummy class:
void moo()
{
class dummy
{
public:
static void a() { printf("I'm in a!\n"); }
};
dummy::a();
dummy::a();
}
No, it's not allowed. Neither C nor C++ support this feature by default, however TonyK points out (in the comments) that there are extensions to the GNU C compiler that enable this behavior in C.
You cannot define a free function inside another in C++.
As others have mentioned, you can use nested functions by using the gnu language extensions in gcc. If you (or your project) sticks to the gcc toolchain, your code will be mostly portable across the different architectures targeted by the gcc compiler.
However, if there is a possible requirement that you might need to compile code with a different toolchain, then I'd stay away from such extensions.
I'd also tread with care when using nested functions. They are a beautiful solution for managing the structure of complex, yet cohesive blocks of code (the pieces of which are not meant for external/general use.) They are also very helpful in controlling namespace pollution (a very real concern with naturally complex/long classes in verbose languages.)
But like anything, they can be open to abuse.
It is sad that C/C++ does not support such features as an standard. Most pascal variants and Ada do (almost all Algol-based languages do). Same with JavaScript. Same with modern languages like Scala. Same with venerable languages like Erlang, Lisp or Python.
And just as with C/C++, unfortunately, Java (with which I earn most of my living) does not.
I mention Java here because I see several posters suggesting usage of classes and class' methods as alternatives to nested functions. And that's also the typical workaround in Java.
Short answer: No.
Doing so tend to introduce artificial, needless complexity on a class hierarchy. With all things being equal, the ideal is to have a class hierarchy (and its encompassing namespaces and scopes) representing an actual domain as simple as possible.
Nested functions help deal with "private", within-function complexity. Lacking those facilities, one should try to avoid propagating that "private" complexity out and into one's class model.
In software (and in any engineering discipline), modeling is a matter of trade-offs. Thus, in real life, there will be justified exceptions to those rules (or rather guidelines). Proceed with care, though.
All this tricks just look (more or less) as local functions, but they don't work like that. In a local function you can use local variables of it's super functions. It's kind of semi-globals. Non of these tricks can do that. The closest is the lambda trick from c++0x, but it's closure is bound in definition time, not the use time.
Let me post a solution here for C++03 that I consider the cleanest possible.*
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){
cout<<"I'm a lambda!"<<endl;
});
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
(*) in the C++ world using macros is never considered clean.
But we can declare a function inside main():
int main()
{
void a();
}
Although the syntax is correct, sometimes it can lead to the "Most vexing parse":
#include <iostream>
struct U
{
U() : val(0) {}
U(int val) : val(val) {}
int val;
};
struct V
{
V(U a, U b)
{
std::cout << "V(" << a.val << ", " << b.val << ");\n";
}
~V()
{
std::cout << "~V();\n";
}
};
int main()
{
int five = 5;
V v(U(five), U());
}
=> no program output.
(Only Clang warning after compilation).
C++'s most vexing parse again
Yes, and you can do things with them that even C++20 Lambdas don't support. Namely, pure recursive calls to themselves & related functions.
For example, the Collatz Conjecture is that a certain simple recursive function will ultimately produce "1" for ANY positive integer N. Using an explicit local struct and functions, I can write a single self-contained function to run the test for any "N".
constexpr std::optional<int> testCollatzConjecture(int N) {
struct CollatzCallbacks {
constexpr static int onEven(int n) {
return recurse(n >> 1); // AKA "n/2"
}
constexpr static int onOdd(int n) {
if(n==1) return 1; // Break recursion. n==1 is only possible when n is odd.
return recurse(3 * n + 1);
}
constexpr static int recurse(int n) {
return (n%2) ? onOdd(n) : onEven(n); // (n%2) == 1 when n is odd
}
};
// Error check
if(N < 0) return {};
// Recursive call.
return CollatzCallbacks::recurse(N);
}
Notice some things that even c++20 lambdas couldn't do here:
I didn't need std::function<> glue OR lambda captures ("[&]") just to enable my local recursive functions call themselves, or each other. I needed 3 plain-old-functions with names, and that's all I had to write.
My code is more readable and (due to (1)) will also run much faster.
I cleanly separate the recursive logic in "CollatzCallbacks" from the rest of "testCollatzConjecture". It all runs in an isolated sandbox.
I was able to make everything "constexpr" and state-less, so it can all run at compile time for any constant value. AFAIK I'd need c++23 just to achieve the recursion part with state-less lambdas.
Remember: Lambda functions are really just compiler-generated local structs like "CollatzCallbacks", only they're unnamed and only have a single "operator()" member function. You can always write more complex local structs and functions directly, especially in cases like this where you really need them.

hidden g++ reference error

Compiling with GCC 4.8.1 (MinGW) with command: g++ -o test.exe test.cpp
test.cpp:
#include <iostream>
int a = 1, b = 2;
void F()
{
int &r = a;
std::cout << r;
r = b;
std::cout << r;
}
int main ( int, char** )
{
F();
F();
return 0;
}
The expected output is: 1212, but real is: 1222
It works as expected when r is defined as pointer.
void F()
{
int *r = &a;
std::cout << *r;
r = &b;
std::cout << *r;
}
Does someone have any idea where is "the key from the tent"?
In the example with a pointer:
r = &b;
This re-seats the pointer r to point to b. In the example with the reference:
r = b;
You probably think that this is analogous to the example with the pointer, but it is not. References are not re-seatable the way pointers are. Once they are initialized, they become aliases for the thing which they reference. So the line above is exactly equivalent to this:
a = b;
That is, it copies the value stored in b over to a.
The reference example is could be written like this:
void F()
{
std::cout << a;
a = b;
std::cout << a;
}
While the pointer example could be written like this:
void F()
{
std::cout << a;
std::cout << b;
}
Your "problem" is the following line:
int &r = a;
This will create a so called reference pointing to a. While references don't require additional logic when accessing them (i.e. dereferencing; compared to pointers), they still work the same way behind the scenes.
So once you hit the line
r = b;
You'll actually use the reference and update the value of a. In this case r never has it's own value. It will always point at a and essentially be an alias.
In your second example, this is different. The line
int *r = &a;
creates a pointer pointing at a and
r = &b;
will reassign that address, making the pointer now point at b.
In short, when you assign some other value (address) to a pointer, you change the pointer and it will point somewhere else. However, when assigning a new value to a reference, you're actually updating the inital value where it's referencing to, not the reference itself.
//global variables! remember that this will be like a state
//and will be freed on (data?BSS?stack?) only after end of program.
int a = 1, b = 2;
void F()
{
//You are referencing here,
//meaning, once you change the referee ( r )
//the reference will changed permanently.
//Permanently because you are referring to a global variable.
int &r = a;
std::cout << r;
//You have changed the value of ( r )
//forever!
r = b; //I think you are assuming the you have changed the reference address here?
std::cout << r;
}
void F()
{
//You have declared and initialized a pointer
//that points to global variable.
//w/c means you can also change its value forever!
int *r = &a;
std::cout << *r;
//You have changed the ( r ) address pointing to, not its value!
r = &b;
std::cout << *r;
}
Your code is absolutely fine and it's working according to your instruction.
Suppose a variable has 1000 address b variable 1004 address, now your first line is
int &r = a;
that means r has 1000 address and you did cout<< r //print 1
In second statement r = b that means 1000 address hold value of b means 2;
Now , your scenario has been changed 1000---> 2 and 1004--->2
and again you are calling F();
that's why compiler print twice 2 value. . There is a concept referencing in c++. Hope it
would be useful for u

How C++ reference works

After working 15 years in C++ I found that I don't understand references completely.
class TestClass
{
public:
TestClass() : m_nData(0)
{
}
TestClass(int n) : m_nData(n)
{
}
~TestClass()
{
cout << "destructor" << endl;
}
void Dump()
{
cout << "data = " << m_nData << " ptr = 0x" << hex << this << dec << endl;
}
private:
int m_nData;
};
int main()
{
cout << "main started" << endl;
TestClass& c = TestClass();
c.Dump();
c = TestClass(10);
c.Dump();
cout << "main ended" << endl;
return 0;
}
// prints:
// main started
// data = 0 ptr = 0x0012FF54
// destructor
// data = 10 ptr = 0x0012FF54
// main ended
// destructor
I understand from this test that TestClass instance is created on the stack (is this correct?) and initialized by first TestClass constructor. When is this instance allocated: when the main function is loaded or when the reference assignment is executed? When it is destroyed?
After the second reference assignment, the object address is not changed. Does this mean that the destructor and constructor are applied to the same memory area? Or is the memory deallocated (dynamically? on the stack?) and allocated again?
I know everything about stack and heap-allocated objects lifetime, their constructors and destructors, but I cannot understand what exactly happens in this program.
Edit:
Thanks to all. I tried to reproduce in this test some other (more complicated) program behavior. Your comments helped me to understand both my mistake and another program I am fighting with...
Fixed code is:
int main()
{
cout << "main started" << endl;
TestClass t;
TestClass& c(t);
c.Dump();
c = TestClass(10);
c.Dump();
cout << "main ended" << endl;
return 0;
}
Note from 29.06.2022: After latest edition by Daniel Walker this question looks like complete crap. I am not responsible for this.
Your code suffers from multiple problems and ultimately won't make sense. However, let's hack through it.
1) You can only bind a temporary to a const reference, thus extending its lifetime:
const TestClass & c = TestClass();
2) Now we can't use dump, because you didn't declare it const:
void Dump() const
3) Saying c = TestClass() is an assignment. However, c is now a reference-to-const, which cannot be assigned to, since assignment is non-constant (for obvious reasons). Let's hack around this:
const_cast<TestClass&>(c) = TestClass(10);
Now we've assigned a new value to the temporary-but-extended object c, and all is as it should be:
main started
data = 0 ptr = 0x0xbfa8219c
destructor
data = 10 ptr = 0x0xbfa8219c
main ended
destructor
The pointers are the same because there's only one object, namely the (temporary) one referenced by c. Assigning to it is a hack that's undefined behaviour in general, but we get away with it for the purpose of this demonstration.
The intermediate destructor is that of the second temporary TestClass(10).
TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression.
c.Dump();
TestClass() creates a temporary and you cannot take the reference of it.
const TestClass& c = TestClass();
const qualification extends the life time of the temporary being created until the scope of the object c.
TestClass& c = TestClass();
This wouldn't even compile!
Attempting to bind a temporary to non-const reference would result in compilation error.
However, you can bind a temporary to const reference:
{
const TestClass& c = TestClass();
//use c
//....
}//<-------- the temporary will be destroyed here.
In this case, the life of the temporary extends to the lifetime of the reference, i.e when the reference variable goes out of scope, the temporary will be destroyed as shown above.
1) you can't get not const reference to a temporary object
2) in the line c = TestClass(10); operator=(...) is called
A good way is to compare references to pointers... (references are usually implemented the same way in assembly generally by using the ebx register). The main difference is that reference is constant after initialization...
However, The line const TestClass& c = TestClass(); is parallel to const TestClass* const pc = &TestClass(); so the object will be create and destroyed on the stack, pc will still hold the same address.