Frage

Ich versuche, am unveränderlichen Typ (Klasse) in C ++,

erstellen

Ich habe es so, dass alle Methoden „aka Mitgliederfunktionen“ das Objekt nicht ändern und eine neue Instanz zurückgeben statt.

Ich bin über eine Reihe von Fragen laufen, aber sie alle um die Referenztypen in C ++ drehen.

Ein Beispiel ist, wenn Übergabe von Parametern der gleichen Klasse Art von Referenz:

Imm Imm::someOp( const Imm& p_im ) const
{
   ...
   p_im = p_im.someOtherOp(); //error, p_im is const, can't modify it!
   ...
}

Der Fehler wird durch das Bestehen des Wertes durch Verweis verursacht. Wenn stattdessen ich den Verweis nach Wert vorbei, dann der Fehlerzeile oben würde kein Fehler sein!

Betrachten wir ein Java / C # Beispiel

class Imm
{
    ...
    Imm someOp( Imm p_im )
    {
        ....
        p_im = p_im.someOtherOp(); //ok, you're not modifying the 
                 //original object, just changing the local reference
        ....  
    }
    ....
}

Wie kann ich so etwas wie dies in C ++ zu tun? Ich weiß, ich Zeiger verwenden können, aber dann habe ich in den gesamten Speicher-Management-Chaos führen. Ich will nicht befürchten, die Verweise auf Objekte besitzt.

Im Idealfall würde Ich mag die Klasse entwerfen wie unveränderliche Strings in Python zu sein; Sie können sie, ohne jemals zu bemerken oder sogar zu wissen, verwenden, dass sie unveränderlich sind, und sie nur so tun, als Sie erwarten; sie arbeiten nur.

Bearbeiten

Natürlich habe ich um ihn herum, indem-by-Wert oder durch die Verwendung einer temporären Variable bekommen (was zur Zeit ich tue). Was ich frage über ist „wie Referenzen in C nach Wert zu übergeben ++“

Ich bin die Antwort zu erwarten drehen sich um etwas in der STL, ich bin derzeit die Suche in smart_ptr Familie von Vorlagen.

UPDATE

Danke für die Antworten, ich weiß, es gibt kein Entkommen aus Zeigern. (Siehe meine andere Frage , die wirklich eine ist auf dieser ein Follow-up)

War es hilfreich?

Lösung

In Java und C #, Sie sind wirklich nicht mit einem Verweis zu tun - sie sind eher wie Griffe oder Zeiger. Ein Verweis in C ++ ist wirklich ein anderer Name für das ursprüngliche Objekt, keinen Zeiger auf sie (auch wenn es mit einem Zeiger implementiert werden kann). Wenn Sie einen Wert mit einer Referenz zuweisen, zuweisen Sie auf das Objekt selbst. Es gibt Verwirrung, dass ein Verweis auf initialisieren Sie die = Zeichen verwenden können, aber es ist eine Initialisierung, keine Zuordnung.

 Imm im, im2, im3; 
 Imm &imr = im;  // initialize a reference to im
 imr = im2; // assign im2 to imr (changes the value of im as well)
 Imm *imp = &im; // initialize a pointer to the address of im
 imp = &im3; // assign the address of im3 to imp (im is unnaffected);
 (*imp) = im2; // assign im2 to imp (modifies im3 as well).

Wenn Sie speziell „von Wert Referenzen“ zu übergeben wollen, dann fragen Sie im Wesentlichen für eine contradition in Bezug. Referenzen per Definition sind durch Verweis übergeben. Wie an anderer Stelle erwähnt, können Sie einen Zeiger nach Wert übergeben, oder auch einen geraden Wert. Wenn Sie wirklich wollen, können Sie auf eine Referenz in einer Klasse halten und passieren, dass etwa von Wert:

 struct ImmRef
 {
     Imm &Ref;
     ImmRef(Imm &ref) : Ref(ref) {}
 };

Beachten Sie auch, dass ein const auf eine Referenz angewendet macht die konstante Objekt bezeichnet, nicht die Referenz. Referenzen sind immer konst.

Andere Tipps

Ist das nicht Zuordnung per definitionem kein Dauerbetrieb?

Sie sehen aus wie Sie versuchen, etwas zu einem const Referenz zuzuweisen, die völlig die Idee einer konstante Referenz besiegt.

Ich glaube, Sie können für einen Zeiger anstelle eines Verweises suchen.

Es funktioniert nicht wie das in C ++.

Wenn Sie einen Verweis auf ein Objekt übergeben, Sie übergeben tatsächlich die Adresse im Speicher des Objekts. Referenzen können nicht auf andere Objekte entweder neu gesetzt werden, damit das C ++ Sprichwort „Gemeint ist das Objekt.“ Sie haben eine Kopie zu machen, ihn zu ändern. Java wird hinter den Kulissen für Sie tun. C ++, die Sie gerade, es zu kopieren.

Haben Sie nicht vergessen, die Methode, die Sie als const rufen zu setzen?

EDIT:. So, mit dem const Fest

Vielleicht sollten Sie etwas tun, wie

Imm & tmp = p_im.someOtherOp();

Sie dann den weiteren Betrieb auf der tmp Variable.

Wenn Sie eine Variable oder einen Parameter als const & Sie können es einfach nicht zuordnen.

Überprüfen Sie diese über temporäre Lebensdauer wissen, http://herbsutter.wordpress.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Imm Imm::someOp( const Imm& p_im ) const
{
   ...
   //Imm& im = p_im.someOtherOp();       // will *not* work
   const Imm& im = p_im.someOtherOp();   // will work, but you get a const reference
   ...
}

Sie können aber boost :: shared_ptr

shared_ptr<Imm> Imm::someOtherOp() const
{
  shared_ptr<Imm> ret = new Imm;
  ...
  return ret;
}

shared_ptr<Imm> Imm::someOp(const share_ptr<Imm>& p_im) const
{
  shared_ptr<Imm> im = p_im->someOtherOp();
}

Sie müssen eine neue Kopie Ihrer eingehenden Argument machen. Sie können tun, was Sie in mehreren gleichwertigen Möglichkeiten wollen: 1) Sie Pass-by-Wert könnte:

Imm Imm::someOp( Imm im ) const {
   im = im.someOtherOp();      // local im is a copy, original im not modified
   return im;                  // return by value (another copy)
}

oder 2) Sie können Pass-by-reference und eine Kopie explizit:

Imm Imm::someOp( const Imm & im ) const {
   Imm tmp = im.someOtherOp(); // local tmp is a copy
   return tmp;                 // return by value (another copy)
}

beide Formen sind äquivalent.

C ++ hat etwas besser als unveränderliche Typen-const. Ein einzelner Typ kann wandelbar sein oder nicht, je nach Ihren Bedürfnissen. Das heißt, es sind nützliche Muster für den Umgang mit Kurz Lebensdauer (Near-) Kopien:

void f(const X &x) {
  // Trivial case: unconditional copy
  X x2=transform(x);
  // Less trivial: conditional copy
  std::optional<X> maybe;
  const X &use=need_copy ? maybe.emplace(transform(x)) : x;
  use.go();  // whichever, x or *maybe
}  // *maybe destroyed iff created, then x2 destroyed

std::unique_ptr kann in ähnlicher Weise vor dem C ++ 17, obwohl die Funktion kann dann natürlich Wurf std::bad_alloc verwendet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top