Ist es eine gute Praxis struct-Objekt als Parameter an eine Funktion in C ++ passieren?
Frage
Ich habe versucht, ein Beispiel leben unter:
typedef struct point
{
int x;
int y;
} point;
void cp(point p)
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
}
Das Ergebnis, das ist gedruckt ist:
1
2
, das ist das, was ich erwartet hatte. Meine Frage ist: Hat Parameter p die vollständige Kopie des Objekts p1 erhalten? Wenn ja, dann frage ich mich, ob dies eine gute Praxis? (I angenommen wird, wenn die Struktur in der Größe groß wird, dies eine Menge Kopie Overhead erzeugen wird).
Lösung
Es ist nichts falsch mit structs als Parameter übergeben. Alles wird von Wert in C ++ übergeben, so eine vollständige Kopie tatsächlich gemacht wird.
Die Struktur Sie in Ihrem Beispiel gab klein, so ist es wahrscheinlich kein Problem, wenn Sie es nach Wert übergeben. Aber wenn Sie mit größeren Datenstrukturen arbeiten, können Sie wollen, dass es durch Verweis übergeben.
Beachten Sie jedoch, durch Referenzmittel vorbei, wenn man die Struktur in Ihrer Funktion ändern, Ihre ursprüngliche Struktur wird geändert werden. Achten Sie darauf, das Schlüsselwort const in jedem Fall zu verwenden, in dem Sie die Struktur nicht ändern. Dadurch erhalten Sie eine sofortige Information über, wenn Ihre Funktionen, die Informationen nicht ändern oder nicht.
Ihr Beispiel zur Arbeit mit Verweis auf diese Weise modifiziert werden:
typedef struct point
{
int x;
int y;
} point;
void cp(const point& p) // You can know that cp doesn't modify your struct
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
void mod_point(point& p) // You can know that mod_points modifies your struct
{
p.x += 1;
p.y += 1;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
mod_point(p1);
cp(p1); // will output 2 and 3
}
Andere Tipps
Ja, es ist nichts falsch mit diesem und ja, p
ist eine vollständige Kopie p1
. Ich würde keine struct
mit zwei int
s groß nennen, aber wenn die struct
groß wird, und wenn Sie es nicht in der Funktion Körper zu verändern, braucht man bedenkt es durch konstante Referenz übergeben:
void cp(const point& p)
{
// ...
}
Bevor ich eine Antwort auf Ihre Frage geben (Sie es am Ende dieses Beitrags finden), hier eine kurze Zusammenfassung der Möglichkeiten Sie haben Argumente für eine Funktion übergeben:
1. Copy-konstruierten Objekte (Pass-by-Wert):
void cp(point p);
Dies ist Pass-by-Wert. Ein temporäres point
Objekt erstellt und kopier konstruiert aus, was auch immer point
Objekt, das Sie in cp
passieren. Sobald die Ausführung verlässt die cp
Funktion wird das temporäre Objekt zerstört wird.
Beachten Sie, dass, da die Funktion auf einer Kopie arbeitet, was auch immer an die Funktion übergeben wurde, können Sie das lokale point
Objekt ändern, so viel wie Sie wollen, das ursprüngliche Objekt des Anrufers wird nicht beeinträchtigt. Es gibt keine Möglichkeit, dieses Verhalten zu ändern, mit Pass-by-value-Parametern.
2. Verweise auf Objekte (Pass-by-reference):
void cp(point& p);
Dies ist pass-by-reference. Die eigentliche Aufgabe der Funktion übergeben verfügbar ist (und möglicherweise Änderungen vorbehalten) innerhalb der Funktion. Wenn Sie nicht möchten, dass die Funktion der Lage sein, das Objekt in gebenen zu ändern, erklärt die Parameter als const point&
:
void cp(const point& p);
3. Zeiger auf Objekte (Pass-by-reference):
void cp(point* p);
Dies ist auch Pass-by-reference, mit einem paar feinen Unterschieden. Ein bemerkenswerter Unterschied ist, dass Sie einen Null-Zeiger auf die Funktion übergeben können. Dies ist nicht möglich mit Referenzen, weil Referenzen muss initialisiert werden und danach nicht mehr neu eingesetzt werden können. - Wie bei Referenzen, wenn Sie nicht zulassen cp
wollen ändert die übergebenen in point
, erklärt ihn als const:
void cp(const point* p);
Antwort auf Ihre Frage:
Pass-by-value-Parameter sind nicht von Natur aus schlecht in keiner Weise. Natürlich gibt es Typen, für die Kopie Konstruktion teuer ist (zum Beispiel sehr große oder komplexe Objekte), oder wo es bestimmte Nebenwirkungen (zum Beispiel mit std::auto_ptr
). In diesen Fällen sollten Sie vorsichtig sein. Ansonsten ist es nur ein weiteres Merkmal von C ++, die seinen durchaus sinnvoll Gebrauch hat.
void cp(point p){
}
wird es von Wert
void cp(point *p){
}
wird es durch Bezugnahme
Genau wie jede andere Datenvariable.
In Java ist das Szenario anders. Passing Objekte immer durch Bezugnahme gehen.
Sie der Punkt struct Fall ist, passieren „Wert“, was bedeutet, dass die gesamte Struktur kopiert wird. Für große Datentypen, kann dies in der Tat langsam sein.
Sie können als Verweis das Objekt betrachten
void cp(point& p) // p may be altered!
oder sein konstante Referenz
void cp(const point& p) // p may not be altered!
Sehen Sie Möglichkeiten, Objekte zu vermeiden, indem sie Wert übergeben. Das Objekt ist nicht nur ‚kopiert‘, sondern ist so konstruiert kopieren. So beinhaltet diese Kopie Konstruktor aufrufen und die Kette der Kopierkonstruktoren, wenn Ihr Objekt zusammengesetzt ist, oder von mehreren Objekten abgeleitet. Pass durch Verweis, wenn möglich.
void cp (Punkt & p const) const {
cout << p.x << endl;
cout << p.y << endl;
}