Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference variable in C++

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

}
like image 732
Sal Avatar asked Dec 06 '11 21:12

Sal


People also ask

Does C have reference variable?

No, it doesn't.

What is the reference variable?

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.

Why do we use reference variables?

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.

What is the reference operator in C?

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.


3 Answers

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).

like image 131
David Rodríguez - dribeas Avatar answered Nov 15 '22 06:11

David Rodríguez - dribeas


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.

like image 30
Martin York Avatar answered Nov 15 '22 08:11

Martin York


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.

like image 31
matthias Avatar answered Nov 15 '22 08:11

matthias