假设我有GPoint的以下代码片段,它具有复制构造函数,赋值运算符和析构函数. GCircle也是如此,它有一个名为GetCentre()的函数,它返回Gpoint对象(Center)的副本.
在main或ButtonClick()中,如下所示,调用GPoint& Center = circle.GetCentre()是安全/有效的吗?通过这样做(如果有效),我们将节省调用赋值运算符的时间!
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 }
解决方法
该代码无效C(即使VS接受它),因为您无法将非const引用绑定到rvalue(函数返回的临时值).
至于性能的特定问题,并考虑到你绑定了一个const引用,没有任何优势.编译器将在调用函数中创建一个未命名的变量,然后将引用绑定到该变量,因此无论如何都要执行复制.
无论如何,为了澄清副本上的一些内容,将根据编译器是否可以删除副本来执行或不执行副本,并且通常它可以执行.我所知道的所有编译器都通过在调用者堆栈中分配对象并将指向未初始化内存的指针传递给函数来实现对象的调用约定(对寄存器来说太大).该函数依次使用该内存来创建返回的对象,避免从返回的对象复制到GPoint中的变量p = circle.GetCentre();,从circle.c_Centre执行单个副本到p(或到未命名的变量)如果你绑定一个常量的引用).