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) {}.
Related
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;
}
struct A {
A(int) : i(new int(783)) {
std::cout << "a ctor" << std::endl;
}
A(const A& other) : i(new int(*(other.i))) {
std::cout << "a copy ctor" << std::endl;
}
~A() {
std::cout << "a dtor" << std::endl;
delete i;
}
void get() {
std::cout << *i << std::endl;
}
private:
int* i;
};
const A& foo() {
return A(32);
}
const A& foo_2() {
return 6;
}
int main()
{
A a = foo();
a.get();
}
I know, returning references to local values is bad. But, on the other hand, const reference should extend a temporary object lifetime.
This code produce an UB output. So no life extention.
Why? I mean can someone explain whats happening step by step?
Where is fault in my reasoning chain?
foo():
A(32) - ctor
return A(32) - a const reference to local object is created and is returned
A a = foo(); - a is initialized by foo() returned value, returned value goes out of scope(out of expression) and is destroyed, but a is already initialized;
(But actually destructor is called before copy constructor)
foo_2():
return 6 - temp object of type A is created implicitly,a const reference to this object is created(extending its life) and is returned
A a = foo(); - a is initialized by foo() returned value, returned value goes out of scope(out of expression) and is destroyed, but a is already initialized;
(But actually destructor is called before copy constructor)
Rules of temporary lifetime extension for each specific context are explicitly spelled out in the language specification. And it says that
12.2 Temporary objects
5 The second context is when a reference is bound to a temporary. [...] A temporary bound to the returned value in a function return statement
(6.6.3) persists until the function exits. [...]
Your temporary object is destroyed at the moment of function exit. That happens before the initialization of the recipient object begins.
You seem to assume that your temporary should somehow live longer than that. Apparently you are trying to apply the rule that says that the temporary should survive until the end of the full expression. But that rule does not apply to temporaries created inside functions. Such temporaries' lifetimes are governed by their own, dedicated rules.
Both your foo and your foo_2 produce undefined behavior, if someone attempts to use the returned reference.
You are misinterpeting "until function exit". If you really want to use a const reference to extend the life of an object beyond foo, use
A foo() {
return A(32);
}
int main() {
const A& a = foo();
}
You must return from foo by value, and then use a const reference to reference the return value, if you wish to extend things in the way you expect.
As #AndreyT has said, the object is destroyed in the function that has the const &. You want your object to survive beyond foo, and hence you should not have const &
(or &) anywhere in foo or in the return type of foo. The first mention of const & should be in main, as that is the function that should keep the object alive.
You might think this return-by-value code is slow as there appear to be copies of A made in the return, but this is incorrect. In most cases, the compiler can construct A only once, in its final location (i.e. on the stack of the calling function), and then set up the relevant reference.
Hello can anyone help me with this?
I have a class with member by reference:
class name{
int& broj;
string ulica;
And have constructor:
public:
kuca(int b, string s) :broj(b)
{
ulica = s;
}
and info class for output
void info(){
cout << broj << ulica << endl;
}
};
When i create object and try to output it
int isbn = 1;
name a(isbn, "text");
a.info();
for reference value i am getting junk/random value it seems, while other attribute is written fine:
-858993460 text
A reference member always has the danger of becoming dangling: when the original object to which the reference refers goes out of scope. In your case, this happened instantly (as the object was a temporary), but even if you follow the suggestion
kuca(int&b, const string&s) : broj(b), ulica(s) {}
^^^^^
you can easily get into trouble. For example
kuca make_kuca()
{
int x=7;
return {x,"bad"};
}
auto k=make_kuca();
when the returned object's reference member refers to a variable (x) that has just gone out of scope.
Therefore, reference data members should be used with care to ensure that their lifetime never exceeds that of they variable they refer to.
You have to write at least
kuca( int &b, string s) :broj(b)
^^^^^^
{
ulica = s;
}
Otherwise variable b is a local variable/object of the constructor that will be destroyed after executing the constructor and the reference will be invalid.
change your ctor signature as follows:
kuca(int& b, string s) :broj(b)
note the int& instead of int. Then, the parameter b will refer to the variable isbn rather than to some call stack location.
It should be noted that with the original signature
kuca(int b, string s) : broj(b)
you're taking a reference of the parameter that's a copy passed on the stack. So, when the info() method is called, then broj refers to a location on the call stack rather than to the variable isbn. That is why it appears to print a "random" value.
You're storing a reference to the parameter b, which exists only during the constructor call. After the constructor call you're left with referencing an int that doesn't exist.
As everyone already said, you probably meant this...
kuca(int b, string s) :broj(b)
to be
kuca(int& b, string s) :broj(b)
There isn't any performance benefit to passing an int by reference though, and the reference is invalid as soon as the int goes out of scope which could create a difficult bug to track down.
My personal preference is to pass by address whenever the variable can be mutated.
class name {
public:
kuca(int* b, string s) : broj(b), ulica(s);
private:
int* broj;
string ulica;
}
That turns the above into a compile time error. Using a reference as a class member is easy to use incorrectly.
1st code:
#include <iostream>
using namespace std;
class demo
{
int a;
public:
demo():a(9){}
demo& fun()//return type isdemo&
{
return *this;
}
};
int main()
{
demo obj;
obj.fun();
return 0;
}
2nd code:
#include <iostream>
using namespace std;
class demo
{
int a;
public:
demo():a(9){}
demo fun()//return type is demo
{
return *this;
}
};
int main()
{
demo obj;
obj.fun();
return 0;
}
what is the difference between these two codes as both are working in gcc?i am new here so forgive me if my way of asking is wrong.
demo & fun() returns a reference to the current object. demo fun() returns a new object, made by copying the current object.
Both are valid but are different. In the first case demo& fun() a reference to the same object is returned, in the second case a new object is created. While both are the same, the semantics differ, run this example:
#include <iostream>
struct test {
int x;
test() : x() {}
test& foo() { return *this; }
test bar() { return *this; }
void set( int value ) { x = value; }
};
int main() {
test t;
t.foo().set( 10 ); // modifies t
t.bar().set( 5 ); // modifies a copy of t
std::cout << t.x << std::endl; // prints 10
}
Apart from what #Erik said about the return type, a little excursus on the this-pointer:
The following is equivalent:
struct my_struct{
my_struct* get_this() const { return this; }
};
my_struct obj;
my_struct* obj_this = ob.get_this();
std::cout << std::boolalpha; // to display true/false instead of 1/0
std::cout << "&obj == obj_this = " << &obj == obj_this << "\n";
The this pointer is just the pointer to that object, you can think of it as a hidden parameter. It's more understandable in the C way:
typedef struct my_struct{
int data;
// little fidgeting to simulate member functions in c
typedef void (*my_struct_funcptr)(struct my_struct*,int);
my_struct_funcptr func;
}my_struct;
// C++ does something similar to pass the this-pointer of the object
void my_struct_func(my_struct* this, int n){
this->data += n;
}
my_struct obj;
obj.data = 55;
// see comment in struct
obj.func = &my_struct_func;
obj.func(&obj, 15);
// ^^^^ - the compiler automatically does this for you in C++
std::cout << obj.data; // displays 70
Consider your function.
demo fun(){return *this;}
Here you are returning by value so one temporary object will be created which will be destroyed, once you assign the return value of fun to some other object.
While in case when you pass the reference, no object will be created newly, but it will pass actual object and even after assigning function return value object will not destroy till main object(used inside fun, in ur case its the object calling the function) won't go out of scope.
The concept you are trying to understand can be explained in more detail with other example.
consider function that is taking object as argument and returning object as argument.(also consider we have object that contains a pointer, we will assign value to pointer by first allocating memory to pointer and a destructor, which will free memory hold by pointer of object). Now when you return object as pass by value, temporary object will be created, that will have exact copy of main object(and temporary object's pointer will also point to same address or you can say holds the same address). Now inside main(), you assign/initialize any object with return value(object) of function. But when your temp object will be destroyed after assigning value, it will also free the memory because of destructor and when you try to fetch the same address value through assigned object(inside main() ) you will get error as that memory has been already freed.
But if you would have return value using reference, object returned by object won't destroy as main obj(inside function or through which we have called the function) is in scope and your pointer won't loose its memory. Making possible for assigned object to fetch address value through its pointer and avoid undesirable result.
In code 1 demo obj creates a fresh copy of demo. obj is initialised using demo's default constructor 'demo():a(9){}'. obj.fun() returns a reference to (already existing) obj.
In code 2 obj.fun() creates a new demo type object using demo's copy constructor (in your case it is compiler generated) and returns that copy to the caller.
Both code are valid.
1st code fun() is returning a reference to current object
2nd code fun() is returning the copy (by value) of the object
For 1st case, If you decide to return by value
then prefer to return a const
reference; i.e. const demo& fun();
and later you can copy it if needed.
Simply returning reference makes the
object modifiable, which may
accidently edit the content without
intent
For 2nd case, Do NOT return the object by value,
because it can create unnecessary
temporary copy which will effect
the memory/performance of your code
I wrote the following code, and I was expecting to get
5
6
6
6, but I got 5 6 5 0 instead. It seems that "val" gets the reference correctly in the beginning, but then it gets lost. Does anybody know where is my mistake?
class Count {
public:
void add() {
val++;
}
void print() {
cout << val << endl;
}
Count(int c): val(c) {
}
private:
int &val;
};
int main() {
int c = 5;
Count teste(c);
teste.print();
teste.add();
teste.print();
cout << c << endl;
teste.print();
return 0;
}
Your constructor should take the parameter by reference, not by value.
The issue here is you are binding a reference to a parameter passed by value. This should be illegal but maybe it isn't. (Does a parameter passed by value have the same status as a temporary and does that apply to primitive types too?)
What compiler is this?
As SpaceCowboy points out if your constructor takes a reference parameter it will work. It should do, it is the normal way to wrap a reference. Of course val will be invalid once c goes out of scope.
You set your private member val as a reference to the local variable c in your constructor. Once you exit the constructor, its a reference to some random value on your stack.
Yes. Either change 'int & val' to 'int val' or change 'Count(int c)' to 'Count(int & c)', that will do the job. by now you're receiving a copy in the c'tor and because you assign that copy to a reference you will get undefined behavior because when the flow gets out of the constructor's scope, the copy will be terminated hence your object will hold a reference to a random place on stack!