Reputation: 170
Consider the following template class
template <typename T>
class A {
public:
virtual T const& getContent() = 0;
};
I derive this class using 'int*' as type 'T', as follows
class A1 : public A<int*> {
private:
int a;
public:
int* const& getContent() { return &a; }
};
I got the following warning: 'returning reference to local temporary object'.
Questions:
Does the compiler implicitly instantiate a local temporary object of type 'int * const' from '&a' before returning its reference?
As I do know that A.a really exists, then can I just ignore this warning? Will there be any undesirable side-effects of using this code?
What is the proper way of handling this situation? Do I need to work with the member variable 'int *a' instead. This would be cumbersome.
Upvotes: 2
Views: 1300
Reputation: 8576
First of all...
int* const&
Is the same as...
int *const&
Edit: Originally, I wrongly stated it was equivalent to const int*&
. Sorry, that was my fault.
And, references to pointers are more "cumbersome" than pointer themselves (at least IMHO), don't you think so? There's a reason pointers and references shall never be mixed (unless it's a consecuence of template instantiation, of course)...
int const&*
This is impossible, invalid, and last but no least, insane. Although there's no practical way for references to be implemented other than by pointers, they are not objects, in the sense that they (themselves) don't have a sizeof
that does not equals that of their referenced type, and the fact that they don't have address at all, at least as far as the Sacred Writings of N4296 are concerned.
But... pointers are objects! The expression &a
returns a rvalue (that is basically an object without an address) of type int*
. Now, the statement return &a;
will take that value and wrap it up in a reference, because...
T
can be extended by means of it being holded in a reference of type const T&
. However, you can't use this to return references to temporary rvalues.Now, because all this stuff implies that you're returning a reference to a temporary rvalue in an unallowed way, you where tempted and falled into Undefined Behaviour.
The solution? Simply don't use references to pointers at all in the first place...
int const *getContent() { return a; }
Or, if you prefer it, use references, but not pointers...
int const &getContent() { return *a; }
Now, to the questions!
int*
, not int *const
, although the latter gets implicitly casted into the former.I hope this has led some light on you!
Upvotes: 0
Reputation: 17704
A.a
exists, but that's not the issue. What you are returning is not a pointer to int
, but a reference to a pointer to int
, i.e. it is a double indirection. To be specific, a temporary int*
was created inside getContent
that pointed to A.a
. A reference to that temporary was returned, and then the temporary was destroyed. Using the result of getContent
will be undefined behavior.int* a
, and then simply return a
in your function. Returning a const reference is a common way to expose the fully functionality of a data member without allowing the user of the class to mutate it, messing up your class' invariants.Upvotes: 7
Reputation: 9403
This is incorrect:
T const& getContent() = 0;
You can do:
T const getContent() = 0;
int* const getContent() { return &a; }
Upvotes: 0