Frage

class mystring {
 friend ostream& operator<<(ostream &out, const mystring ss) {
        out << ss.s;
        return out;
    }
private:
    string s;
public:
    mystring(const char ss[]) {
        cout << "constructing mystring : " << ss << endl;
        s = ss;
    }
};

void outputStringByRef(const mystring &ss) {
 cout << "outputString(const string& ) " << ss << endl;
}

void outputStringByVal(const mystring ss) {
 cout << "outputString(const string ) " << ss << endl;
}

int main(void) {
    outputStringByRef("string by reference");
    outputStringByVal("string by value");
    outputStringByRef(mystring("string by reference explict call mystring consructor"));
    outputStringByVal(mystring("string by value explict call mystring constructor"));
} ///:~

In Anbetracht der oben genannten Beispiel,konnten wir nicht ändern Sie die pass-by-reference-variable,konnten wir weder ändern Sie die pass-by-value-variable.Die Ausgabe der einzelnen Methoden ist die gleiche.Da gibt es keinen Unterschied zwischen diesen zwei Möglichkeiten,warum C++ - Unterstützung in beiden Methoden?

vielen Dank.

War es hilfreich?

Lösung

Es gibt einen Unterschied zwischen den beiden. Beachten Sie Folgendes:

#include <iostream>
#include <string>
using std::string;

string g_value;

void callback() {
    g_value = "blue";
}

void ProcessStringByRef(const string &s) {
    callback();
    std::cout << s << "\n";
}

void ProcessStringByValue(const string s) {
    callback();
    std::cout << s << "\n";
}

int main() {
    g_value = "red";
    ProcessStringByValue(g_value);
    g_value = "red";
    ProcessStringByRef(g_value);
}

Ausgabe:

red
blue

Nur weil ein Verweis const in einer Funktion ist, bedeutet nicht, dass die referand kann nicht über andere Referenzen geändert werden (die Lage eines Objekts mehrere Verweise oder Zeiger auf es aufweist, wird „Aliasing“ genannt). Somit gibt es eine andere eine konstante Referenz zwischen Geben, und einen Wert const Passing - in dem Fall der Referenz, könnte das Objekt ändern, nachdem der Anruf durchgeführt wird. Im Fall des Wertes, hat die Angerufene eine private Kopie, die nicht ändern wird.

Da sie verschiedene Dinge tun, C ++ können Sie wählen, welche Sie wollen.

Es gibt Folgen für die Leistung oder so - wenn Sie nach Wert übergeben, wird eine Kopie gemacht, werden muss Kosten, die. Aber der Compiler weiß dann, dass nur möglicherweise Ihre Funktion alle Verweise auf diese Kopie haben kann, die anderen Optimierungen ermöglichen könnte. ProcessStringByRef können den Inhalt der Zeichenfolge nicht geladen werden für den Druck bis callback() zurückgekehrt ist. ProcessStringByValue kann, wenn der Compiler denkt dabei ist schneller.

In der Regel kümmern Sie über die Kopie, nicht die Reihenfolge der Ausführung von Anweisungen, weil in der Regel die Kopie ist viel teurer. Also in der Regel passieren Sie durch Verweis wo möglich für Objekte, die nicht-trivial zu kopieren. Aber die Möglichkeit, manchmal von Aliasing hat wirklich schwerwiegende Folgen für die Leistung, indem verhindert bestimmte Optimierungen obwohl kein Aliasing tatsächlich auftritt. Deshalb "strenge Aliasing Regeln" exist, und das restrict Stichwort in C99.

Andere Tipps

f(const string&) nimmt Zeichenfolge durch const Referenz: fis direkt auf dem String-Objekt arbeitet als Referenz übergeben: es keine beteiligt kopieren. const verhindert Änderungen an dem ursprünglichen Objekt though.

f(const string) nimmt einen String-Wert, der mittels f eine Kopie der Original-Zeichenkette angegeben. Auch wenn Sie const fallen, wenn sie von Wert, jede Änderung an der Schnur vorbei geht verloren, wenn f zurückkehrt.

Ich weiß nicht genau, was Sie mit „warum C beiden Methoden unterstützen ++?“. Es ist nur allgemeine Überlastung Regeln, die gelten.

f(string s) Pass von Wert der String s, mit anderen Worten eine Kopie erstellt und initialisiert sie mit dem Wert der Zeichenfolge, die Sie übergeben. Jede Änderung der Kopie, nicht an der ursprünglichen Zeichenfolge propagiert werden Sie übergeben die Funktion aufzurufen. In f(const string s) const ist überflüssig, weil man ohnehin nicht den ursprünglichen Wert ändern kann.

In f(const string& s) stattdessen die Zeichenfolge nicht kopiert wird, aber sie passieren einen Verweis darauf. Dies geschieht normalerweise, wenn Sie eine große Aufgabe haben, so dass der „Pass-by-Wert“ kann einen Overhead erzeugen (deshalb c ++ unterstützt beiden Methoden). Vorbei Referenz bedeutet, dass Sie den Wert des „großen“ Objekt ändern Sie weitergeben, sondern auch wegen der const Bezeichner, Sie können es nicht ändern. Es ist eine Art von „Schutz“.

Ihre Aufgabe konnte enthält ein wandelbar Mitglied, das sogar mit einem modifiziert werden kann, const-Referenz

Mit outputStringByRef müssen Sie sicherstellen, dass die Variable Sie einen Verweis auf Reste vorbei sind lebendig und unverändert, solange outputStringByRef es braucht. mit outputStringByVal die Variable, die Sie übergeben können oder Umfang erhalten aussterben und die Kopie, dass die Funktion ist noch in Ordnung.

Es gibt (fast) kein Unterschied in Bezug auf die Möglichkeit, die Zeichenfolge innerhalb der Funktion zu ändern. Allerdings gibt es einen großen Unterschied in Hinblick darauf, was passiert ist. Die const mystring &ss Überlastung nimmt einen const Bezug auf die Saite. Obwohl es nicht ändern kann, ist es das gleiche adressierte Speicher Wesen. Wenn die Zeichenfolge lange ist dies ein großer Faktor sein kann (vorausgesetzt, dass die Zeichenfolge verwendet nicht implementiert Kopie -on-Schreib ). Die const mystring ss Form wird eine Kopie des Strings zur Verfügung gestellt werden, so unterschiedliche Speicher angesprochen werden.

Tatsächlich ist die const mystring &ss Form könnte die Zeichenfolge ändern, wenn ein const_cast<mystring&> verwendet wurde -. Obwohl ich würde das nicht empfehlen, hier

Stellen Sie sich vor Sie wollen zu drucken ein Objekt, dass kann nicht kopiert werden:

Thread th;
// ...
cout << th; // print out informations...

Die Referenz-version wird keine Kopie der thread, aber nehmen Sie sich die Adresse von th und erstellen Sie einen alias, um es.Die andere version würde versuchen, kopieren Sie die Faden, wenn die übergabe durch Wert - aber das kopieren kann nicht sinnvoll für ein solches Objekt (würde es einen weiteren thread dann?).

Es kann Ihnen helfen, zu denken, ein Objekt kopieren als ein Objekt Klonen.Kopieren th oben in C++ nicht nur bedeuten, haben andere Griff auf das gleiche Objekt wie in Java - es bedeutet implizit Klon-Objekt gekennzeichnet, und haben eine vollständige Kopie von es.Also die Frage ist ähnlich wie "Warum muss Java unterstützen Object.clone und das kopieren von Referenzen?" - beide haben unterschiedliche Zwecke.

Und dann es ist eine Frage der Leistung zu, nachdem alle.Sie nicht wollen, kopieren und jedes mal, wenn Sie etwas passieren, um für Ressourcen-hungrig Objekte.

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