Подтвердить что ты не робот

Как вернуть объект класса по ссылке в С++?

У меня есть класс Object, который хранит некоторые данные.

Я хотел бы вернуть его по ссылке, используя следующую функцию:

    Object& return_Object();

Тогда в моем коде я бы назвал это следующим образом:

    Object myObject = return_Object();

Я написал такой код, и он компилируется. Однако, когда я запускаю код, я последовательно получаю ошибку seg. Каков правильный способ возврата объекта класса по ссылке?

4b9b3361

Ответ 1

Вероятно, вы возвращаете объект, который находится в стеке. То есть return_Object(), вероятно, выглядит так:

Object& return_Object()
{
    Object object_to_return;
    // ... do stuff ...

    return object_to_return;
}

Если это то, что вы делаете, вам не повезло - object_to_return вышел из области действия и был разрушен в конце return_Object, поэтому myObject ссылается на несуществующий объект. Вам либо нужно вернуть значение, либо вернуть Object, объявленный в более широкой области, или new ed в кучу.

Ответ 2

Вы можете использовать только

     Object& return_Object();

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

  class  MyClass{
      private:
        Object myObj;

      public:
         Object& return_Object() {
            return myObj;
         }

         Object* return_created_Object() {
            return new Object();
         }

         bool modify_Object( Object& obj) {
            //  obj = myObj; return true; both possible
            return obj.modifySomething() == true;
         }
   };

Ответ 3

Вы можете возвращать нелокальные объекты по ссылке. Деструктор может иметь недействительный какой-либо внутренний указатель или что-то еще.

Не бойтесь возвращать значения - быстро >

Ответ 4

Ну, возможно, это не очень красивое решение в коде, но в интерфейсе вашей функции оно действительно красиво. И это также очень эффективно. Это идеально, если для вас важнее второй (например, вы разрабатываете библиотеку).

Хитрость такова:

  • Строка A a = b.make(); внутренне преобразуется в конструктор A, т.е. как если бы вы написали A a(b.make());.
  • Теперь b.make() должен получить новый класс с функцией обратного вызова.
  • Все это может обрабатываться только классами без шаблона.

Вот мой минимальный пример. Проверьте только main(), как видите, это просто. Внутренние элементы не являются.

С точки зрения скорости: размер класса Factory::Mediator - всего 2 указателя, что больше 1, но не более. И это единственный объект во всем, что передается по значению.

#include <stdio.h>

class Factory {
  public:
    class Mediator;

    class Result {
      public:
        Result() {
          printf ("Factory::Result::Result()\n");
        };

        Result(Mediator fm) {
          printf ("Factory::Result::Result(Mediator)\n");
          fm.call(this);
        };
    };

    typedef void (*MakeMethod)(Factory* factory, Result* result);

    class Mediator {
      private:
        Factory* factory;
        MakeMethod makeMethod;

      public:
        Mediator(Factory* factory, MakeMethod makeMethod) {
          printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
          this->factory = factory;
          this->makeMethod = makeMethod;
        };

        void call(Result* result) {
          printf ("Factory::Mediator::call(Result*)\n");
          (*makeMethod)(factory, result);
        };
    };
};

class A;

class B : private Factory {
  private:
    int v;

  public:
    B(int v) {
      printf ("B::B()\n");
      this->v = v;
    };

    int getV() const {
      printf ("B::getV()\n");
      return v;
    };

    static void makeCb(Factory* f, Factory::Result* a);

    Factory::Mediator make() {
      printf ("Factory::Mediator B::make()\n");
      return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
    };
};

class A : private Factory::Result {
  friend class B;

  private:
    int v;

  public:
    A() {
      printf ("A::A()\n");
      v = 0;
    };

    A(Factory::Mediator fm) : Factory::Result(fm) {
      printf ("A::A(Factory::Mediator)\n");
    };

    int getV() const {
      printf ("A::getV()\n");
      return v;
    };

    void setV(int v) {
      printf ("A::setV(%i)\n", v);
      this->v = v;
    };
};

void B::makeCb(Factory* f, Factory::Result* r) {
      printf ("B::makeCb(Factory*, Factory::Result*)\n");
      B* b = static_cast<B*>(f);
      A* a = static_cast<A*>(r);
      a->setV(b->getV()+1);
    };

int main(int argc, char **argv) {
  B b(42);
  A a = b.make();
  printf ("a.v = %i\n", a.getV());
  return 0;
}