valores tipos retornan referencia que programacion por parametros funciones ejemplos con c++ reference segmentation-fault return-by-reference

tipos - ¿Cómo devolver un objeto de clase por referencia en C++?



parametros por referencia java (5)

Tengo una clase llamada Objeto que almacena algunos datos.

Me gustaría devolverlo por referencia usando una función como esta:

Object& return_Object();

Entonces, en mi código, lo llamaría así:

Object myObject = return_Object();

He escrito código así y lo compila. Sin embargo, cuando ejecuto el código, siempre obtengo una falla de seg. ¿Cuál es la forma correcta de devolver un objeto de clase por referencia?


Bueno, tal vez no sea una solución realmente hermosa en el código, pero es realmente hermosa en la interfaz de su función. Y también es muy eficiente. Es ideal si el segundo es más importante para usted (por ejemplo, está desarrollando una biblioteca).

El truco es este:

  1. Una línea A a = b.make(); se convierte internamente en un constructor de A, es decir, como si hubiera escrito A a(b.make()); .
  2. Ahora b.make() debería dar como resultado una nueva clase, con una función de devolución de llamada.
  3. Todo esto puede manejarse bien solo por clases, sin ninguna plantilla.

Aquí está mi ejemplo mínimo. Verifica solo el main() , como puedes ver es simple. Los internos no lo son.

Desde el punto de vista de la velocidad: el tamaño de una clase Factory::Mediator es solo de 2 punteros, que es más que 1 pero no más. Y este es el único objeto en todo lo que se transfiere por valor.

#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; }


Probablemente estés devolviendo un objeto que está en la pila. Es decir, return_Object() probablemente tiene este aspecto:

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

Si esto es lo que está haciendo, no tiene suerte: object_to_return ha quedado fuera del alcance y se ha destruido al final de return_Object , por lo que myObject hace referencia a un objeto inexistente. Debe devolver por valor o devolver un Object declarado en un ámbito más amplio o una new edición en el montón.


Solo puede devolver objetos no locales por referencia. El destructor puede haber invalidado algún puntero interno, o lo que sea.

No tengas miedo de recuperar valores, ¡ es rápido !


Solo puedes usar

Object& return_Object();

si el objeto devuelto tiene un alcance mayor que la función. Por ejemplo, puede usarlo si tiene una clase en la que está encapsulada. Si creas un objeto en tu función, usa punteros. Si desea modificar un objeto existente, páselo como argumento.

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; } };


Te mostraré algunos ejemplos:

Primer ejemplo, no devuelva el objeto de alcance local, por ejemplo:

const string &mainip(const string &s) { string ret=s; // operator ret return ret; }

no puedes devolver ret por referencia, porque ret se destruye al final.

Segundo ejemplo, puedes volver por referencia:

const string &shorterString(const string &s1,const string &s2) { return s1.size()<s2.size()?s1:s2; }

puede volver por referencia para s1 y s2 aún existe.

Tercer ejemplo:

char &get_val(string &str,string::size_type ix) { return str[ix]; }

código de uso de la siguiente manera:

string s("123456"); cout<<s<<endl; char &ch = get_val(s,0); ch =''A''; cout<<s<<endl; // A23456

porque después de regresar por referencia el objeto todavía existe;

Cuarto ejemplo

class Student{ public: string m_name; int age; string& getName(); }; string& Student::getName(){ // you can return by reference return m_name; } // you can return by reference, after this function stu object is still exists string& Test(Student &stu) { return stu.m_name; }

ejemplo de uso:

Student stu; stu.m_name = ''jack''; string name = stu.getName(); // //or string name2 = Test(stu);

Quinto ejemplo:

class String{ private: char* str_; public: String& operator=(const String& str); }; // for example a=b=c usage String& String::operator =(const String &str) { if (this == &str) { return *this; } delete [] str_; int len = strlen(str.str_); str_ = new char[len+1]; strcpy(str_,str.str_); return *this; }