2016-10-13 4 views
1

Ich habe eine einfache Frage bezüglich Referenz-Update in C++. Betrachten Sie unter C++ Code:Referenz-Update in C++

class A 
{ 
    int b; 

    public: 
    int& setb(); 
    int getb(); 
    A(); 
    A &operator= (const A &t) 
    { 
     cout<<"Assignment called"<<endl; 
    } 
    A(int i):b(i) { 
     cout<<"Copy contructor called"<<endl; 
    } 
}; 

int A::getb() 
{ 
    cout<<this->b<<endl; 
} 

int& A::setb() 
{ 
    return b; 
} 

A::A() 
{ 
    cout<<"constructor called"<<endl; 
} 

int main() 
{ 
    A a; 
    cout<<"About to set reference"<<endl; 
    a.setb()=5; 
    a.getb(); 

    return 0; 
} 

Wenn ich b über Referenz aktualisieren, wie wird der Wert kopiert? Gibt es einen Standard-Kopierkonstruktor, der aufgerufen wird?

+1

Eine Referenz erstellt keine Kopie. – Barmar

+1

Eine Referenz ist im Wesentlichen ein versteckter Zeiger. – Barmar

+0

aber in diesem Fall Wenn ich ein privates Mitglied der Klasse aktualisieren, sollte es von einem Objekt der Klasse richtig aktualisiert werden? –

Antwort

2

Der einfachste Weg, zumindest für mich zu verstehen, ist vorstellbar, dass Sie mit Zeigern arbeiten, nicht Referenzen:

int* A::setb() 
{ 
    return &b; 
} 

Nun, wenn Sie dies tun:

*(a.setb())=5; 

Es wird klar was passiert. Referenzen tun genau dasselbe, aber ohne all das *& Hokuspokus. Ihre Auftrags-/Kopierkonstruktoren haben damit überhaupt nichts zu tun. Wenn Ihr Feld nicht int, sondern ein benutzerdefinierter Typ ist, würde der Zuweisungsoperator diesen-Typ aufrufen. Sie könnten in dieser Aufgabe tun, was Sie wollen.

Ein interessanter Trick ist, dass Ihr setb kann eine „intelligente Referenz“ Typ zurück, die tatsächlich b aktualisiert, kann aber etwas mehr:

class TwoIntsRef { 
public: 
    TwoIntsRef(int &a, int &b) : 
     a(a), 
     b(b) 
    {} 
    TwoIntsRef& operator=(int c) 
    { 
     cout << "TwoIntsRef Assignment called" << endl; 
     a = c; 
     b = c; 
     return *this; 
    } 
private: 
    int &a; 
    int &b; 
}; 

Und dann tun Sie dies:

TwoIntsRef A::setb() 
{ 
    return TwoIntsRef(b, c); 
} 

Und das:

a.setb() = 5; 

Jetzt setzt es beide b und c.

Dies ist eigentlich ein sehr nützlicher Trick, der eine Menge Dinge tun kann. In einem meiner Projekte musste ich Legacy-Code portieren, der sich stark auf die Big-Endian-Byte-Reihenfolge verließ. Damit es auf der Little Endian-Hardware funktioniert, musste ich den gesamten Speicherzugriff durch intelligente Referenzen ersetzen, die die Bytes automatisch austauschen. Kein sehr effizienter Weg, aber der einzige, der in diesem speziellen Projekt funktionieren würde.

1

Nein, wenn Sie b über Referenz aktualisieren, wird kein Kopierkonstruktor aufgerufen, ob implizit oder explizit definiert.

A Copy-Konstruktor aufgerufen wird, wenn bei der Definition (Speicher ist noch nicht zugeordnet), werden Sie Wert auf das Objekt zuweisen ex

A obj = a;

Zuweisungsoperator aufgerufen wird, wenn das Objekt bereits definiert (Speicher ist bereits reserviert) und Sie möchten die Felder des Objekts ändern.

0

Durch Ihren Code sehe ich, dass Sie den Standard-Kopierkonstruktor des C++ - Compilers verwenden. Es wird den Kopierkonstruktor jedes nicht statischen Members Ihrer Klasse verwenden.Beachten Sie, dass der erzeugte Konstruktor in Ihrem Fall mag aussehen:

A(const &A other) 
: b(other.b) 
{} 

und es wird int diesen Fällen aufgerufen werden:

A a; 
... 
A b = a; 
... 
A c(a); 

Mit anderen Worten wird der Kopierkonstruktor aufgerufen werden, wenn Ihr Konstrukt neues Objekt von einem anderen Objekt derselben Klasse. Ihr Konstruktor von int ist kein Kopierkonstruktor.

Zweitens, warum Sie b privat einstellen, während jeder es über Ihre setb() ändern kann? Ich denke, ein besserer Weg, um Ihre setb() zu implementieren ist:

void A::setb(const int& val) { 
    b = val; 
}