In the below code the variable a is passed to a constructor by reference, received by the parameter x. Then x is passed as a reference to an attribute. The attribute is then initialized with value 3. The program outputs the value 3 when running.
MY QUESTION
Shouldn't the program crash or show 2 because after the constructor is called
x should go out of scope and be released and its address should be freed right. and trying to write to it should give a memory access violation. However in this case the x is still in program control holding the address of 'a'
Is this valid c++ behavior or am i missing something?
#include <iostream>
#include <conio.h>
using namespace std;
class myclass {
public:
int& attribute;
myclass(int& x):attribute(x) {
}
void func() {
attribute = 3;
}
};
int main() {
int a = 2;
myclass obj(a);
obj.func();
std::cout << a;
_getch();
}
No this program is fine. attribute is a reference to a. The fact that x has gone out of scope is neither here nor there.
If you changed your code to
myclass(int x):attribute(x)
then that would be a problem.
The behavior of the program line by line
variable "a" is initialized with value 2
int a = 2;
Initialize obj with the variable a
myclass obj(a);
First x becomes the reference to a, then attribute becomes the reference to x. Consequently, attribute becomes the reference to a, which has the value 2 at the moment.
myclass(int& x):attribute(x) {}
Call func() of obj
obj.func();
attribute is the reference to a.
Both "attribute" and "a" are changed to 3. Consider them as the same,
single variable, just with difference alias.
That means, at this moment, attribute and a refers to the same variable,
and can be used interchangeably.
void func() {
attribute = 3;
}
Related
Why the output is 30 here? And how fun()=30 is valid? What is meant by assigning function a value? And why removing static keyword throws segmentation fault?
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Let's walk through your program step by step:
inside main() fun() is called.
fun() has a static variable x (static means, that x is stored in a special part of memory and not on the stack, so its value is preserved between function calls) (It's like having a global variable that is only visible from inside fun())
fun() returns a reference to x (references are almost like pointers)
You write to the returned reference of x, so x actually gets changed! (You don't write to the function)
now x is 30 and fun() returns 30 on the next call.
I hope this answers your first three questions.
Why you get a segmentation fault without the static keyword:
In this case x does exist on the stack. So whenever you call fun() some memory gets allocated on the stack to hold x. When fun() returns, this memory will be deallocated.
Now, the reference returned by fun(), will reference a piece memory, that is not allocated by your program anymore. In other words, the returned reference will reference a memory address, that does "not belong to your program", thus you are not allowed to write to it. And so you get a segmentation fault.
Can we assign values to function:
To answer the actual title of your question: Yes, we can, using function pointers:
int foo(int x) {
return x + 1;
}
int bar(int x) {
return x * 2;
}
void main() {
int(*f)(int) = foo;
// int the function pointed to returns an int
// (*f) f is the name of the function pointer
// (int) the function pointed to takes on int as paramter
// = foo; f now points to the function foo()
(*f)(3); // the same as foo(3), returns 4
f = bar; // now f points to bar()
(*f)(3); // the same as bar(3), returns 6
}
fun() returns a reference to static variable x, to which you assign the value 30. You don't assign anything to the function itself. In fact, it is not possible to assign anything to a function in C++.
If I have a unique pointer and I create an alias for it in a function, and that alias goes out of scope, why doesn't the original unique_ptr also get destroyed? After all, 'b' as defined in the function below is basically the same object in memory as 'x'. What is going on behind the scenes?
#include <iostream>
#include <memory>
void testfunc(std::unique_ptr<int>& x) {
std::unique_ptr<int>& b = x;
}
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(a);
std::cout << *a << std::endl; // 5
}
What you're using is a reference, and a reference in C++ is a distinct type from what it is referencing. You can interact with an object through a reference, but the reference itself and the object being referred to have separate lifetimes. When one is destroyed, the other doesn't automatically get destroyed. This means you can pass a reference into a function and then at the end of a function when the reference is destroyed the original object is still valid. This allows passing around large complex objects without needing to copy or even moving them. It's a implementation detail, but it's common for compilers to simply use a pointer "behind the scenes" as references.
As a side note, this aspect of references in C++ leads to the infamous dangling reference issue. If you hold a reference to some object and that object is destroyed the reference you have is now technically invalid, and you'll invoke undefined behavior if you use it. Unfortunately there is nothing built into the language to automatically detect or deal with this situation. You must architect your program to avoid it.
A reference is can be considered like an alias to an element, hence it references another variable by taking up its value and working just like it does, but it doesn't get destroyed until called by the destructor or forcibly destroyed by the programmer which will also destroy the variable it references... since a reference is just an editable alias... However their lifespan differs since a non-reference type can be moved and it becomes out of scope...
"What is going on behind the scenes?"
Inside the memory, the reference allows us to change the value of an element and if often used instead of pointers which were a common practice in C... But, its value cannot be moved unless passed... A reference's value won't change unless changed using an assignment operation directly or indirectly i.e, from the function parameter x which itself is an alias...
Like: x = std::make_unique<int>(6); will change the value of a to 6 instead... But what you have done here instead is...
auto& b = x;
Nothing actually happens except the value that x(references to a) is referencing to is copied and passed to b (which just acts like another alias)... So it is similar to doing: auto& b = a;, but since a is outside the scope, it references a's value indirectly...
#include <iostream>
#include <memory>
void testfunc(std::unique_ptr<int>& x)
{
auto& b(x); // 'b' is an alias of 'x' and 'x' is an alias of 'a'
b = std::make_unique<int>(6); // Setting 'b' to 6 meaning setting 'a' to 6...
/* Now you can't do 'x = b' since you cannot assign a value to an alias and it is
like a 'circular assignment operation'...*/
}
int main()
{
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5 : Nothing happens, just initialization...
testfunc(a); // It does not affect the reference...
std::cout << *a << std::endl; /* 6 : Since reference is an 'alias', you
changed 'a' as well...*/
} // It is freed after use by the destructor...
So, a general advice from people would be that you should avoid references if you are unsure of what it does (It can change the real variable if you are unknown of its consequences)... and take some time to learn about them...
If you destroy the original however..., all the references themselves will become invalidated... In such a case, when trying to access the value of destroyed (nullified) object is undefined causing undefined behavior...
#include <iostream>
#include <memory>
void testfunc(std::unique_ptr<int>& x) { // you take a reference to a unique_ptr
std::unique_ptr<int>& b = x; // which will do nothing to the lifetime of
} // the unique_ptr you pass to the function,
// then you assign the passed parameter
// to another reference. again, that does
// nothing to the lifetime of the original.
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(a);
std::cout << *a << std::endl; // 5
}
After all, 'b' as defined in the function below is basically the same object in memory as 'x'.
Not at all. x is a reference. A reference is not an object, and no constructor or destructor is called for it. There are no "aliases" for variables. There are for types, also known as typedefs.
Consider the same code with pointers instead:
void testfunc(std::unique_ptr<int>* x) {
std::unique_ptr<int>* b = x;
}
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(&a);
std::cout << *a << std::endl; // 5
}
The only time a reference can affect the lifetime of an object is when a reference binds to a temporary, but even then, it extends the lifetime rather than reducing it:
struct A {};
int main() {
{
A(); // Constructed and destructed
}
{
A const& a = A(); // Constructed
// Other instructions
} // Destructed
}
Demo
I want to write a class with a reference as a field, but am finding that even this simple code which initializes the reference and prints its value fails:
struct Referencer {
explicit Referencer(int in) : num(in) {}
void print() {
std::cout << num << std::endl;
}
int #
};
int main() {
int longlived = 500;
Referencer ref(longlived);
ref.print();
}
The result is garbage (no errors are thrown, nor does the program segfault). My understanding is that the variable longlived has the same lifetime as the instance of Referencer, as they are both declared in the stack and have the same scope. Therefore, the field num should point to valid stack memory when ref.print() is called. Why is this not the case?
The constructor of Referencer takes the argument by value. So in holds a copy of the value in longlived. You then initialized num to a reference to in, which get's destroyed as soon as the constructor returns.
If you want num to hold a reference to the object used as the argument in the constructor, pass in by reference like explicit Referencer(int &in) : num(in) {}.
Say I have a this code:
class A{
...
};
//somewhere else
A a;
A & ref = a;
a = A();
Does ref still reference the a? Regardless of how many assignments happen? That is, the assignment operator would never cause a memory location change, right?
Yes it does so. Actually after the last line ref will point to whatever a points to.
Whatever you do to the reference is also done to the original object.
So all you do is defining an alternative name for the same variable.
There are few things you need to remember
i) references are different from pointers
ii) pointer may be undefined /null but reference should always be associated with a variable.
iii) pointer may be able to point to different variable at different time; reference always associated with the same variable throughout it's life.
Check this question
Does ref still reference the a?
Yes . Look at the code below. It shows how the assignment does not change the memory location...
A a;
std::cout<<"a:"<< &a<<std::endl;
A & ref = a;
std::cout<<"ref:"<< &ref<<std::endl;
a = A();
std::cout<<"a:"<< &a<<std::endl;
The output looks like so:
a:0x7fffaaa5fcaf
ref:0x7fffaaa5fcaf
a:0x7fffaaa5fcaf
Does ref still reference the a?
Yes.
A reference variable is an alias for another variable.
ref is bound to a, to it's original variable memory. Assigning something to a will also affect ref since it refers to the memory of a. Below is a small example:
class A {
public:
A(int x, int y) : m_x(x), m_y(y) {}
A() = default;
int m_x;
int m_y;
};
int main()
{
A a;
A &ref = a;
a = A(500, 500);
cout << ref.m_x << " " << ref.m_y << endl;
}
Output is 500 500
Consider the following code:
int * p;
void Set()
{
int i = 7;
p = & i; // potentially disastrous
}
I know that pointing to a value that may be overwritten is bad but I recall reading that there was a way to prevent a value such as i from being lost when declared and then pointed to in this way. I've scoured my text book but have had trouble finding the exact text elaborating on this and am starting to think I may have even imagined it. Is there a way of safely pointing to a temporary value declared inside of a function? A way of making the temporary value i no longer temporary?
Thanks for all your help in advance!
I recall reading that there was a way to prevent a value such as i from being lost when declared and then pointed to in this way
The closest thing to what you mention (if I understood your sentence correctly) is the rule which allows prolonging the lifetime of a temporary when bound to a reference (§ 12.2/5 of the C++11 Standard):
struct X { int x = 0; };
X foo() { return X(); }
int main()
{
X const& x = foo(); // The lifetime of the object bound to x is prolonged
x.x = 42; // This is OK
}
However, there is no such rule for pointers nor for objects that are not temporaries.
A way of making the temporary value i no longer temporary?
In your example, i is not a temporary: it is an object with automatic storage duration. A temporary is an object whose life-time (usually) terminates at the end of the full expression that creates it (with the exception mentioned above and a few more listed in § 12.2/4-5).
taking const ref to an temporary extends liifetime of this temporary up to the end of scope of this const reference, however in your example you are not taking address of temporary but local automatic object i.
so to extends lifetime of temporary do simply:
const int& iref=int(3);
int a= iref;
//..do stuff with iref, i.e:
printf("iref: %d\n", a);
output:
iref: 3
RUN SUCCESSFUL (total time: 46ms)
The value of i has to reside in memory somewhere. If you declare it inside a function, it is likely to be allocated on the stack and will be lost when the function returns. If you really need the value to always be constant like in your example, then what you need is to declare it outside the function as static const:
int * p;
static const int i = 7;
void Set()
{
p = & i;
}
If this is not what you need, maybe you can elaborate a bit on your very minimal example code so that we can better understand what you are trying to achieve.
you can use the static keyword.
#include <stdio.h>
int *p;
void set() {
static int x = 7;
p = &x;
}
int main(){
set();
printf("%d", *p);
}
correctly prints 7.
however, I would strongly discourage using such a piece of code in anything but a research on the static keyword and pointers.