有没有一种正确的方法通过C++引用返回一个新的对象实例?

Pat*_*gan 16 c++ return reference object variable-assignment

所以我写了一些代码,我有这样的事情:

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

    public:
    //...
    Rectangle & GetRect( void ) const
    {
        return Rectangle( x, y, w, h );
    }
};
Run Code Online (Sandbox Code Playgroud)

然后在一些代码中:

Rectangle rect = theBox.GetRect();
Run Code Online (Sandbox Code Playgroud)

哪个在我的调试版本中有效,但在发行版中有"问题"通过引用返回Rectangle - 我基本上得到了一个未初始化的矩形.Rectangle类有一个=运算符和一个复制构造函数.在没有弄清楚为什么会破坏的情况下,我实际上更感兴趣的是通过引用返回(新)对象的正确方法,以便复制分配给变量.我只是傻吗?不应该这样做吗?我知道我可以返回一个指针,然后取消引用,但我不愿意.我的某些部分感觉像按值返回会导致对象的冗余复制 - 编译器是否会解决并优化它?

这似乎是一个微不足道的问题.经过多年的C++编码后,我感到尴尬,我不知道这一点,所以希望有人可以为我清除这一点.:)

Ste*_*yle 26

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

  1. 按价值归还
  2. 通过引用返回引用,指向您使用new运算符在堆上创建的内容.
  3. 通过引用将您通过引用收到的内容作为参数返回.[编辑:感谢@ harshath.jr指出这一点]

请注意,当您按照下面的代码中的值返回时,编译器应优化分配以避免复制 - 即,它将通过优化create + assign + copy到create中来创建单个Rectangle(rect).这仅在从函数返回时创建新对象时有效.

Rectangle GetRect( void ) const
{
    return Rectangle( x, y, w, h );
}

Rectangle rect = theBox.GetRect();
Run Code Online (Sandbox Code Playgroud)

  • 再一次,此代码中没有赋值. (5认同)
  • 选项3:通过引用返回您通过引用而作为争论的内容.这在覆盖运算符时尤其适用. (3认同)
  • 指针的例子在这个答案中会很好,比如 Rectangle * GetRect(void) const { return new Rectangle(x, y, w, h) } Rectangle* rect = theBox.GetRect(); 稍后删除矩形; (2认同)

Jar*_*Par 16

不,你不能这样做.基本上,您在此示例中尝试执行的操作是返回对堆栈上的临时变量的引用.返回引用时,它指向的变量将被销毁,因此引用无效.


Bru*_*man 8

按值返回对象(参见下面的示例)实际上可能比您想象的要便宜.编译器通常会优化额外的副本.这称为返回值优化.

    Rectangle GetRect( void ) const
    {
            return Rectangle( x, y, w, h );
    }
Run Code Online (Sandbox Code Playgroud)


Sta*_*ked 5

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

不,不是通过参考。创建新对象有两种方法:

在堆栈上:

Rectangle makeRect()
{
  return Rectangle(x, y, w, h);
}
Rectangle r = makeRect(); // return by value
Run Code Online (Sandbox Code Playgroud)

在堆上:

Rectangle * makeRect()
{
  return new Rectangle(x, y, w, y);
}
Rectangle * r = makeRect(); // returned a pointer, don't forget to delete it later
Run Code Online (Sandbox Code Playgroud)

为什么不做这样的事情呢?

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();
Run Code Online (Sandbox Code Playgroud)

“作业”现在应该可以工作了。(从技术上讲,这不是赋值运算符,而是调用的复制构造函数。)

希望能有所帮助