Как вернуть объект класса по ссылке в С++?
У меня есть класс Object, который хранит некоторые данные.
Я хотел бы вернуть его по ссылке, используя следующую функцию:
Object& return_Object();
Тогда в моем коде я бы назвал это следующим образом:
Object myObject = return_Object();
Я написал такой код, и он компилируется. Однако, когда я запускаю код, я последовательно получаю ошибку seg. Каков правильный способ возврата объекта класса по ссылке?
Ответы
Ответ 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;
}