Есть ли правильный способ вернуть новый экземпляр объекта по ссылке в C ++?

Вы можете сделать следующее с помощью Swift 2.2:

let alertController: UIAlertController = ...
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

и Swift 3.0:

let alertController: UIAlertController = ...
UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
16
задан Patrick Hogan 17 June 2009 в 15:24
поделиться

9 ответов

Вы не можете вернуть ссылку на временный объект в стеке. У вас есть три варианта:

  1. Вернуть по значению
  2. Вернуть по ссылке через указатель на что-то, что вы создали в куче с помощью оператора new.
  3. Вернуть по ссылке то, что вы получили по ссылке в качестве аргумента. [РЕДАКТИРОВАТЬ: Спасибо @ harshath.jr за указание на это]

Обратите внимание, что при возврате по значению, как в приведенном ниже коде, компилятор должен оптимизировать присвоение, чтобы избежать копирования, т.е. он просто создаст один прямоугольник ( rect) путем оптимизации создания + назначения + копирования в файл создания. Это работает только тогда, когда вы создаете новый объект при возврате из функции.

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

Rectangle rect = theBox.GetRect();
26
ответ дан 30 November 2019 в 15:21
поделиться

No you cannot do this. Essentially what you're trying to do in this sample is return a reference to a temporary variable on the stack. By the time the reference is returned, the variable it's pointing to will be destroyed and hence the reference is invalid.

16
ответ дан 30 November 2019 в 15:21
поделиться

Есть ли правильный способ вернуть новый экземпляр объекта по ссылке в 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();

«Назначение» теперь должно работать. (Технически это не оператор присваивания, а вызываемый конструктор копирования.)

Надеемся на помощь

3
ответ дан 30 November 2019 в 15:21
поделиться

Возврат объекта по значению (см. Пример ниже) может быть дешевле, чем вы думаете. Компилятор часто оптимизирует лишнюю копию. Это называется оптимизацией возвращаемого значения .

    Rectangle GetRect( void ) const
    {
            return Rectangle( x, y, w, h );
    }
8
ответ дан 30 November 2019 в 15:21
поделиться

Это невозможно. Ссылка - это еще одна форма указателя, и вы фактически возвращаете адрес объекта, который будет уничтожен (вызван деструктор) и, возможно, даже перезаписан к тому времени, когда вызывающий объект получит управление.

Вы можете либо

  • вызвать новый и вернуть указатель (возможно, вам стоит подумать о интеллектуальном указателе) на объект, выделенный в куче, или
  • возврат по значению, или
  • передать объект по ссылке в функцию, чтобы она заполнила его.
2
ответ дан 30 November 2019 в 15:21
поделиться

Возможно, вас сбивает с толку концепция времени жизни временного. Подумайте:

void f1( const A & a ) {
}

A f2() {
   return A;
}

f1( f2() );

Это нормальный код, и стандарт говорит, что безымянный временный объект, который создает f2, должен висеть достаточно долго, чтобы его можно было использовать в f1.

Однако ваш случай несколько иной. Вещь, которую возвращает ваша функция, является ссылкой, и поэтому безымянный временный объект также является ссылкой. Эта ссылка должна висеть достаточно долго, чтобы быть полезной, но то, к чему она относится.

2
ответ дан 30 November 2019 в 15:21
поделиться

Если прямоугольник побитово выглядит как Box, т.е. состоит из четырех чисел с плавающей запятой (но имеет разные функции-члены), вы можете использовать reinterpret_cast , хотя я бы не рекомендовал его :

    const Rectangle & GetRect( void ) const
    {
            assert(sizeof(Rectangle) == sizeof(Box));
            return reinterpret_cast <Rectangle> (*this);
    }
0
ответ дан 30 November 2019 в 15:21
поделиться
  • Либо вернуть ссылку на внутреннюю часть вашего класса Box (иметь член Rectangle . Возвращение ссылки const ] рекомендуется).
  • или просто вернуть Rectangle . Обратите внимание, что использование идиомы return SomeClass (a, b, c); , вероятно, вызовет оптимизацию возвращаемого значения (RVO) на достойном компиляторе.

Проверьте свой std :: сложная реализация для подробностей.

2
ответ дан 30 November 2019 в 15:21
поделиться

мы можем использовать 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 ));   
  }

};
0
ответ дан 30 November 2019 в 15:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: