Assume I have the following code snippet for GPoint
, which has a copy constructor, assignment operator, and destructor. The same for GCircle
and this has a function named GetCentre()
which returns a copy of the Gpoint
object(Centre
).
In main
or ButtonClick()
, as below is it safe/valid to call GPoint &Centre = circle.GetCentre()
? By doing this (if valid) we would save the time of calling assignment operator!.
class GPoint
{
public:
GPoint();
virtual ~GPoint();
GPoint(double p_dX, double p_dY);
GPoint (const GPoint &Source);
GPoint& operator = (const GPoint &point);
public:
double c_y;
double c_x;
};
class GCircle//:public GShape
{
public:
GCircle();
GCircle(GPoint p_point, double p_dRadius);
~GCircle(){}
operator GPoint&();
operator double&();
double& GetRadius() const ;
GPoint GetCentre() const {return c_Centre;} //Return copy Not a reference
public:
double c_dRadius;
GPoint c_Centre;
};
Dlg::ButtonClick()
{
GPoint Point1(10,2);
GCircle circle(Point1, 100);//100 is the radius.
**GPoint &Centre = circle.GetCentre();** //is this reference safe/valid or invalid
}
No, it doesn't.
A reference variable is a variable that points to an object of a given class, letting you access the value of an object. An object is a compound data structure that holds values that you can manipulate. A reference variable does not store its own values.
The main use of references is acting as function formal parameters to support pass-by-reference. In an reference variable is passed into a function, the function works on the original copy (instead of a clone copy in pass-by-value). Changes inside the function are reflected outside the function.
The reference operator noted by ampersand ("&"), is also a unary operator in c languages that uses for assign address of the variables. It returns the pointer address of the variable. This is called "referencing" operater.
That code is not valid C++ (even if VS accepts it), as you cannot bind a non-const reference to an rvalue (the temporary returned by the function).
As of the particular question of performance, and considering that you were binding a const reference, there is no advantage at all. The compiler will create an unnamed variable in the calling function and then bind the reference to that, so the copy is performed anyway.
To clarify a bit on the copy is performed anyway, the copy will or will not be performed depending on whether the compiler can elide it, and in general it can. All compilers I know, implement the calling convention for your object (too large for registers) by allocating the object in the caller stack and passing a pointer to that uninitialized memory to the function. The function in turn uses that memory to create the returned object, avoiding the copy from the returned object to the variable in GPoint p = circle.GetCentre();
, performing a single copy from circle.c_Centre
to p
(or to the unnamed variable if you bound a reference to constant).
No.
It should not even compile in the current state.
circle.GetCentre();
This returns an object.
Since you do not assign it to the variable it is an unamed temporary object.
temporary can not be bound to a reference (though they can be bound to a const refererence).
// This should be a compiler error
GPoint& Centre = circle.GetCentre();
// This should compile
GPoint const& Centre = circle.GetCentre();
When you bind a temporary to a const reference it's lifespan is extended to the life of the reference.
No, it's not safe or valid. GCircle::GetCentre()
returns-by-value, so the memory where the returned value is temporarily stored will be invalid at the end of the statement. Assigning a piece of data to a reference variable really only stores a pointer to the original's address in memory. Once that memory is invalid, Centre
could be referencing any memory of any type, and will blindly treat it like a GPoint
.
To save a value returned-by-value, you would need to say GPoint Centre = circle.GetCentre();
. If you indeed want a reference to circle
's c_Centre
member, you should rewrite GetCentre()
as such:
GPoint& GetCentre() const {return c_Centre;}
Furthermore, since you probably don't want people outside of circle
to change its centre, you should probably return it as a const GPoint&
:
const GPoint& GetCentre() const {return c_Centre;}
This will cause anyone looking at the new Centre
local variable to think its const
, without changing the way circle
views the same piece of data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With