I have a class whose objects have to pass a reference to themselves to another function.
I discovered that this is a pointer, not a reference. So how do I get the reference to the object that I'm in?
You can get an l-value of yourself to return as a reference by dereferencing the this pointer ie:
return *this;
Since this is a pointer to the object, you can get the object itself by derefrencing it with *this.
The function :
void func(MyClass& obj)
{ }
Calling the function.
func(*this);
Related
When passing an object to a method or function is the object then passed by reference or value when the object is not initiated by the new keyword?
My_object a;
my_function(a);
Is the object then passed to the function as a reference or a value?
void my_function(My_object a){
}
Or do I need to add & ?
void my_function(My_object &a){
}
The way an object is passed depends on the function's parameters and not on the way the object was created.
My_object a means it's passed by value.
For passing by reference you need to use My_object& a. If you do not intend to change the object, you may prefer const My_object& a. This will avoid accidental overwrite.
I'm somewhat confused about the declaration of functions returning const references to temporaries.
In the following code
#include <string>
#include <iostream>
using namespace std;
const string& foo() {
return string("foo");
}
string bar() {
return string("bar");
}
int main() {
const string& f = foo();
const string& b = bar();
cout << b;
}
What is the difference between methods foo and bar ?
Why does foo give me warning: returning reference to local temporary object [-Wreturn-stack-address]. Isn't a copy of the temporary created on const string& f = foo(); ?
string("foo") creates an object of type std::string containing the value "foo" locally in the function. This object will be destroyed at the end of the function. So returning the reference to that object will be invalid once the code leaves that function [1]. So in main, you will never have a valid reference to that string. The same would be true if you created a local variable inside foo.
The WHOLE point of returning a reference is that you don't make a copy, and initializing a reference (string &f = foo() is an initialization) will not create a copy of the original object - just another reference to the same object [which is already invalid by the time the code is back in main]. For many things, references can be seen as "a different name for the same thing".
The lifetime of the referred object (in other words, the actual object the "alias name" refers to) should ALWAYS have a lifetime longer than the reference variable (f in this case).
In the case of bar, the code will make a copy as part of the return string("bar");, since you are returning that object without taking its reference - in other words, by copying the object, so that works.
[1] pedantically, while still inside the function, but after the end of the code you have written within the function, in the bit of code the compiler introduced to deal with the destruction of objects created in the function.
Isn't a copy of the temporary created on const string& f = foo();
Where did you hear that?
Adding const to a reference often allows the lifetime of a temporary with which it's been initialised to be extended to the lifetime of the reference itself. There's never a copy.
Even that's not the case here, though. The object you're binding to the reference goes out of scope at the end of the function and that takes precedence over everything else.
You're returning a dangling reference; period.
Why does foo give me warning: returning reference to local temporary
object [-Wreturn-stack-address].
You are creating a temporary string object inside foo(), and you are returning a reference to that object which will immediately go out of scope (dangling reference).
const string& foo() {
return string("foo"); // returns constant reference to temporary object
} // object goes out of scope
bar() is quite different:
string bar() {
return string("bar"); // returns a copy of temporary string
}
...
const string& b = bar(); // reference an rvalue string
What is the difference between methods foo and bar ?
foo() returns a constant (dangling) reference while bar() returns a copy of a temporary string object.
In both of the cases, a string object is initialized and allocated on the stack.
After returning from the function, the memory segment which contains it becomes irrelevant, and its content may be overridden.
The difference between the functions:
bar function return a copy of the string instance which is created inside it.
foo function returns a reference to the string instance which is created inside it.
In other words, it returns an implicit pointer to its return value, which resides in a temporary memory segment - and that's the reason for your warning.
In ·std::unique_ptr· code in file "memory", I see operator overloading functions as
typename tr1::add_reference<_Ty>::type operator*() const
{
// return reference to object
return (*this->_Myptr);
}
pointer operator->() const
{
// return pointer to class object
return (&**this);
}
What does the &** mean in the second function? Thanks.
this is a pointer to the unique_ptr object.
*this is a reference to the unique_ptr object.
**this is dereferencing the unique_ptr using operator* (i.e. *this->_Myptr).
So, &**this is a pointer to the object pointed at by the unique_ptr (i.e. &(*this->_Myptr)).
As per the posted code, **this is invoking operator* overload which returns a reference to an object. so &**this becomes address of the returned object.
In other words, **this is same as (*this->_Myptr), and &**this is same as &(*this->_Myptr).
I've been reading Myers book and came across the item on returning by reference/pointer vs by value.
The point is, if our function for example is like this:
ClassA& AddSomething(ClassA classA)
{
ClassA tempClassA;
//... do something on tempClassA
return tempClassA;
}
This would not work because we are returning a reference to a object that was created on the stack and it is dead now that the function is done.
He gives two solutions:
Using a local static ClassA inside the function. This has its
problems but atleast we can be sure that object exists.
Return as an object:
ClassA AddSomething(ClassA classA)
{
ClassA tempClassA;
//... do something on tempClassA
return tempClassA;
}
Now if I'm to do:
ClassA obj1;
ClassA obj2 = AddSomething(obj1);
My confusion now is, when executing this line:
A 'copy' of tempClassA is made and passed to the copy constructor
of ClassA (to initialize obj2)? OR
tempClassA is passed itself to the copy constructor of ClassA,
because copy constructor takes a reference.
So basically, whats passed to the copy constructor is a reference to tempClassA (which was created in stack inside the function) or a reference to a copy of tempClassA.
Also, another question I have is, I have read that if I get a reference of a function local variable, in that case the local variable will not be deleted.
For example,
ClassA & classRef = AddSomething(obj1);
In this case, if AddSomething() is returning a reference, then classRef not be pointing to a deleted reference because the local variable will be retained. Have I understood this correctly?
At worst, you're right: a copy of tempClassA is passed to the copy constructor. But compilers are allowed to eliminate that copy and construct the result in place form tempClassA. This is known as the "Return Value Optimization", or RVO. I don't know of a compiler that doesn't do this.
When an object is returned by value, there are two copies taking place: one from the local variable into the return value, and one from the return value into the target object. However, the implementation is allowed to elide one or both of these copies; this is called return value optimisation (RVO) in the first case, and copy elision in the second.
Object some_function() {
return Object(); // copy Object() into return value; candidate for RVO
}
Object another_function() {
Object obj;
return obj; // copy obj into return value; candidate for NRVO
}
Object result = some_function(); // copy return value into result; candidate for copy elision
The second function above is a candidate for a refinement type of RVO called named return value optimisation; the simplest form of RVO applies only to return statements that construct the return value inplace.
Regarding your second question, lifetime extension only applies to const references to objects returned by value; your code in the second question will not extend the lifetime of any object. See Returning temporary object and binding to const reference for more details.
You can never return a function local variable by reference. It would NOT work even if you used const reference to capture the returned value like this:
const ClassA& classRef = AddSomething(obj1);
Because if AddSomething returns a local object by reference, it'll be a dangling reference to a non-existing object by the time classRef gets to reference it.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
warning: returning reference to temporary
I am getting the error "returning reference to temporary" on the second line below.
class Object : public std::map <ExString, AnotherObject> const {
public:
const AnotherObject& Find (const ExString& string ) const {
Object::const_iterator it = find (string);
if (it == this->end()) { return AnotherObject() };
return ( it->second );
}
}
My class implements std::map.
I am new to C++ so I'm guessing its just a syntax error. Any help?
If your function looks like this:
AnotherObject& getAnotherObject()
{
. . .
Object::const_iterator it = find ("lang");
if (it == this->end()) { return AnotherObject() };
. . .
}
the problem is that the AnotherObject() you've returned will be destroyed as soon as the function exits, and so the caller to your function will have a reference to a bogus object.
If your function returned by value however:
AnotherObject getAnotherObject()
then a copy will be made before the original is destroyed and you'll be OK.
return AnotherObject(); creates an object which is destroyed before function exit - temporaries are destroyed at the end of the expression that contains them[*], and the expression AnotherObject() creates a temporary.
Since the function returns by reference, this means that by the caller even gets a chance to see that reference, it no longer refers to a valid object.
It would be OK if the function were to return by value, since the temporary would be copied[**].
[*] With a couple of situations that don't, but they don't help you here.
[**] Actually there's an optimization called "copy constructor elision" which means the temporary needn't be created, copied and destroyed. Instead, under certain conditions the compiler is allowed to just create the target of the copy in the same way it would have created the temporary, and not bother with the temporary at all.
You're creating a temporary value on the stack AnotherObject() and returning it right before it gets destroyed. Your function's caller would get garbage, and so it's forbidden.
Maybe you want to allocate it on the heap and return a pointer to it instead?
return new AnotherObject();
Alternatively, declare your function to return a "copy" to your object, instead of a reference like I'm assuming you are returning right now:
AnotherObject f()
{
return AnotherObject(); // return value optimization will kick in anyway!
}
The function must be declared to return a reference, and a reference has to refer to an object that will continue to exist after the function exits. Your temporary "AnotherObject()" is destructed right after the return, so that obviously won't work. If you can't change the method signature, you may need to throw an exception instead of returning an error value.
You should change the return type of your function from "AnotherObject&" to "AnotherObject" and return that object by value. Otherwise it will go just like Blindy described
You shouldn't return a reference to a temporary which is destroyed at the end of the line, nor a reference to a local which is destroyed at the end of the function.
If you want to keep the current signature, you'd have to add a static constant instance that you can return as a default.
#include <iostream>
template <class T>
class X
{
T value;
static const T default_instance;
public:
X(const T& t): value(t) {}
const T& get(bool b) const
{
return b ? value : default_instance;
}
};
template <class T>
const T X<T>::default_instance = T();
int main()
{
X<int> x(10);
std::cout << x.get(true) << ' ' << x.get(false) << '\n';
}
You may also return by value or return a pointer in which case you can return NULL.
The call to AnotherObject's constructor creates a new instance on the stack, which is immediatly destroyed when the method returns.
It is most likely not a good idea to create and return new object if the find fails. The calling code will have no way to tell if the object returned is a previously existing object present in the data structure.
If you do want to do this, then you should add the new object to the data structure and then return an iterator pointing to the new object IN THE DATA STRUCTURE.
Something like this:
if (it == this->end()) {
it = this->insert(pair<ExString, AnotherObject>( string, AnotherObject() ));
return it->second;
}
I personally think that this is a bit of a hack, but as long as you really stick to the const'ness of the returned reference you should be able to return a statically constructed instance of AnotherObject whose only "raison d'etre" is to be the "not found" return value of your function. Make it a static const private member of your class Object for example, and you should be ok as long as a default constructed instance of AnotherObject is not a valid value to be contained in an instance of Object.