C++ 在C+;中是否有通过引用返回新对象实例的正确方法+;?

C++ 在C+;中是否有通过引用返回新对象实例的正确方法+;?,c++,object,reference,return,variable-assignment,C++,Object,Reference,Return,Variable Assignment,所以我写了一些代码,我有这样的想法: class Box { private: float x, y, w, h; public: //... Rectangle & GetRect( void ) const { return Rectangle( x, y, w, h ); } }; 然后在后面的一些代码中: Rectangle rect = theBox.GetRect(); 这在我的调试构建中起作用,但

所以我写了一些代码,我有这样的想法:

class Box
{
    private:
    float x, y, w, h;

    public:
    //...
    Rectangle & GetRect( void ) const
    {
        return Rectangle( x, y, w, h );
    }
};
然后在后面的一些代码中:

Rectangle rect = theBox.GetRect();
这在我的调试构建中起作用,但在发行版中,通过引用返回该矩形存在“问题”——我基本上得到了一个未初始化的矩形。矩形类有一个=运算符和一个复制构造函数。不必解释为什么会出现这种情况,实际上我更感兴趣的是通过引用返回(新)对象的正确方法,以便将复制赋值给变量。我只是在傻吗?不应该这样做吗?我知道我可以返回一个指针,然后在赋值时取消引用,但我不愿意。我的某些部分感觉按值返回会导致对象的冗余复制——编译器是否能解决这一问题并对其进行优化


这似乎是个微不足道的问题。我感到很尴尬,我不知道这经过多年的C++编码,所以希望有人能为我澄清这一点。p> 不,你不能这样做。基本上,在这个示例中,您要做的是返回对堆栈上临时变量的引用。当引用返回时,它指向的变量将被销毁,因此引用无效

不能返回对堆栈上临时对象的引用。您有三种选择:

  • 按值返回它
  • 通过指向您使用新运算符在堆上创建的内容的指针,通过引用返回
  • 通过引用返回通过引用收到的作为参数的内容。[编辑:感谢@harshath.jr指出这一点]
  • 请注意,当您按以下代码中的值返回时,编译器应优化赋值以避免复制-即,它将通过优化create+assign+copy创建一个矩形(rect)。这仅在从函数返回时创建新对象时有效

    Rectangle GetRect( void ) const
    {
        return Rectangle( x, y, w, h );
    }
    
    Rectangle rect = theBox.GetRect();
    
    • 返回对
      类内部的引用(使用
      矩形
      成员。建议返回
      常量
      引用)
    • 或者只返回一个
      矩形
      。注意,使用习惯用法
      返回SomeClass(a,b,c)
      可能会触发一个新的编译器

    查看您的
    std::complex
    实现以了解详细信息。

    您可能会被临时用户生命周期的概念弄糊涂。考虑:

    void f1( const A & a ) {
    }
    
    A f2() {
       return A;
    }
    
    f1( f2() );
    
    这是OK代码,标准规定f2创建的无名临时文件必须挂起足够长的时间才能在f1中使用


    然而,你的情况有所不同。函数返回的东西是一个引用,因此无名的临时对象也是一个引用。该引用必须挂起足够长的时间才有用,但它所指的东西不需要。

    这是不可能的。引用是指针的另一种形式,实际上,您返回的对象的地址将被销毁(调用析构函数),甚至可能在调用方接收到控制时被覆盖

    你也可以

    • 调用new并返回指向堆分配对象的指针(也许您应该考虑智能指针),或者
    • 按值返回或
    • 通过引用将对象传递到函数中,使其充满

    按值返回对象(参见下面的示例)实际上可能比您想象的要便宜。编译器经常优化多余的副本。这就是所谓的


    如果矩形按位看起来像长方体,即由四个浮点数组成(但有不同的成员函数),则可以使用reinterpret_cast,但我不建议这样做:

        const Rectangle & GetRect( void ) const
        {
                assert(sizeof(Rectangle) == sizeof(Box));
                return reinterpret_cast <Rectangle> (*this);
        }
    
    const矩形和GetRect(void)const
    {
    断言(sizeof(矩形)==sizeof(长方体));
    返回重新解释的铸件(*本);
    }
    
    如果我们想使用新的、安全的内存泄漏,我们可以使用auto_ptr

    class Box  { 
    
      private:    float x, y, w, h;   
    
      public:    
    
      //...    
    
      std::auto_ptr<Rectangle> GetRect( void ) const   
      {        
          return std::auto_ptr<Rectangle> ( new Rectangle( x, y, w, h ));   
      }
    
    };
    
    类框{
    专用:浮动x、y、w、h;
    公众:
    //...    
    标准::自动ptr GetRect(无效)常量
    {        
    返回std::auto_ptr(新矩形(x,y,w,h));
    }
    };
    
    有没有一个正确的方式返回一个新的 C++中的引用对象实例 不,不是通过引用。有两种方法可以创建新对象:

    在堆栈上:

    Rectangle makeRect()
    {
      return Rectangle(x, y, w, h);
    }
    Rectangle r = makeRect(); // return by value
    
    在堆上:

    Rectangle * makeRect()
    {
      return new Rectangle(x, y, w, y);
    }
    Rectangle * r = makeRect(); // returned a pointer, don't forget to delete it later
    
    为什么不像这样

    class Box
    {
      private:
        Rectangle mRectangle;
    
      public:
        Box(float x, float y, float w, float h) :
          mRectangle(x, y, w, h) // Forgive me for making assumptions
                                 // about the inner workings of your
                                 // code here.
        {
        }
    
        const Rectangle & GetRect() const
        {
          return mRectangle;
        }
    };
    
    Rectangle rect = theBox.GetRect();
    
    “任务”现在应该可以工作了。(从技术上讲,这不是赋值运算符,而是正在调用的复制构造函数。)


    希望对您有所帮助

    那么您是说如果它是const-rectang&GetRect(…),那么它是正确的吗?问题不在于constness,而在于您有引用的东西是在堆栈上创建的。@pbhogan,不。我不应该在我的答案中添加const单词。那是我的错误。您只需在此处按值返回该值。请注意,代码中没有赋值。选项3:按引用返回您作为参数收到的内容。这在重写运算符时特别有用。在这个答案中,指针的示例会很好,比如矩形*GetRect(void)const{return new Rectangle(x,y,w,h)}矩形*rect=theBox.GetRect();稍后删除rect;你当然是对的。我在动态语言上花了太多时间——我开始期望临时语言的生命周期遵循引用。我的选项总结得很好,谢谢。我已经尽可能地实现了您的最后一个选项,但是这里的示例有点过于简单。Box实际上是更复杂的东西,GetRect返回一个计算过的矩形。不管怎样,你的第一个选择就是我应该做的。。。我只是想比编译器更聪明,我猜:p
    class Box
    {
      private:
        Rectangle mRectangle;
    
      public:
        Box(float x, float y, float w, float h) :
          mRectangle(x, y, w, h) // Forgive me for making assumptions
                                 // about the inner workings of your
                                 // code here.
        {
        }
    
        const Rectangle & GetRect() const
        {
          return mRectangle;
        }
    };
    
    Rectangle rect = theBox.GetRect();