繁体   English   中英

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

[英]Is there a right way to return a new object instance by reference in C++?

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

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

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

然后在一些代码中:

Rectangle rect = theBox.GetRect();

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

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

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

  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();

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

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

    Rectangle GetRect( void ) const
    {
            return Rectangle( 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();

“任务”现在应该有效。 (从技术上讲,这不是一个赋值运算符,而是一个被调用的复制构造函数。)

希望能帮到你

  • 返回对Box类内部的引用(具有Rectangle成员。建议返回const引用)。
  • 或者只返回一个Rectangle 注意使用成语return SomeClass(a,b,c); 可能会在合适的编译器上触发返回值优化(RVO)

检查std::complex实现以获取详细信息。

你可能会对临时生命的概念感到困惑。 考虑:

void f1( const A & a ) {
}

A f2() {
   return A;
}

f1( f2() );

这是好的代码,标准说f2创建的无名临时必须挂起足够长的时间才能在f1中使用。

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

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

你也可以

  • 调用new并返回一个指针(也许你应该想到一个智能指针)到堆分配的对象或
  • 按价值或
  • 通过引用将对象传递给函数,以便填充它。

如果矩形按位看起来像Box,即包含四个浮点数(但有不同的成员函数),你可以使用reinterpret_cast ,虽然我根本不会推荐它:

    const Rectangle & GetRect( void ) const
    {
            assert(sizeof(Rectangle) == sizeof(Box));
            return reinterpret_cast <Rectangle> (*this);
    }

我们可以使用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 ));   
  }

};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM