Wann ein Zeiger als Parameter wann eine Referenz?
-
Bei Arrays kann man keine Referenzen verwenden, da muss man Zeiger verwenden.
-
DrGreenthumb schrieb:
verdammt, mein Edit kam jetzt aber vor deiner Frage.
Nein, kam es nicht. HAHA!
-
Eine Referenz ist ein intern von C++ verwalteter Zeiger, nicht mehr und nicht weniger, also nichts besonders Tolles. Die Syntax ist einfacher, weil man den Dereferenzierungsoperator beim Zugriff auf den Inhalt einspart.
Vorteilhaft/Nachteilig ist, dass man eine Referenz beim Erzeugen mit einem gültigen Wert belegen muss. Wirklich sicher sind Referenzen jedoch nicht, da man z.B. lokal gültige Entitäten diesen Referenzen zuweisen kann. Damit zeigen diese "C++-Zeiger" dann auch nur in verbotenes Gelände.
C++ benötigt nach wie vor Zeiger, z.B. beim Anlegen von Speicher auf dem Heap.
-
godlikebot schrieb:
Bei Arrays kann man keine Referenzen verwenden, da muss man Zeiger verwenden.
oder anders ausgedrückt: Arrays werden automatisch als Referenz übergeben.
Nein, kam es nicht. HAHA!
naja, zumindest mein Klick auf den Edit-Button :p
-
öhm, arrays als Pointer zu lesen ist keine schöne Sache, nicht umsonst müht man sich mit der STL oä. Containern ab, um sich nicht um Speicher und co kümmern zu müssen, um dann am Ende einer Funktion ein Pointer auf ein Array übergeben zu müssen.
Da nimmt man doch lieber den Iterator Syntax, der lässt sich nämlich auf alle Container übertragen, sogar auf irgend welche Listen
template<typename Iter> void foo(Iter begin,Iter end);
Bei mir kommen Zeiger eigentlich nur noch im LowLevel Code vor. Ansonsten nehm ich lieber SmartPointer oä. wo man ansonsten Zeiger benutzt.
-
Ich verwende eigentlich immer Referenzen und nur im Notfall Zeiger. Folgende Punkte, die oft sowohl Nachteil als auch Vorteil sein können fallen mir ein:
Zeiger:
- Bei der Übergabe von Objekten sieht man anhand des & Operators, dass eine Übergabe per Pointer stattfindet.
- Ein Zeiger kann auch 0 sein, so dass die aufgerufene Funktion diesen Fall beachten muß.
- Innerhalb der Funktion muß beim Zugriff eine manchmal syntaktisch lästige Dereferenzierung stattfinden.
Referenz:
- Beim Aufruf der Funktion ist nicht ersichtlich ob per Value oder per Reference übergeben wurde.
- Eine Referenz kann nicht 0 sein, so dass die aufrufende Funktion dafür sorgen muß, dass das Objekt gültig ist.
- Einfachere Syntax zum Aufrufen von Memberfunktionen.
-
Die obige Gegenüberstellung zeigt, dass Referenzen nicht wirklich vorteilhaft sind, sondern nur anders agieren. Daher sollte man diese Diskussion nicht ideologisch betreiben, sondern akzeptieren, dass pointer ein wichtiger und notwendiger Bestandteil der Sprache C++ sind.
Marc++us hat es in seinem Buch "OOP für Dummies" wie folgt treffend beschrieben (S. 209):
"Referenzen sind von der technischen Realisierung her nur Zeiger, aber sie sehen etwas anders aus. Ein Zeiger im Schafspelz."
Wer mit Zeigern nicht klar kommt, der sollte sich eine andere Programmiersprache als C++ suchen. Da helfen auch keine noch so hübschen "wrapper".
-
DrGreenthumb schrieb:
Das war so das, was mir als erstes in den Sinn kam, bis ich darüber nachgedacht habe und mir auch kein Beispiel eingefallen ist.
endlich mal einer, der es tut! der herr sei gepriesen!
und ich leiere wiedermal meinen text runter...
an sich ist es dem compiler egal, ob zeiger oder ref. refs haben zwei technische vorteilchen.
a) da sie nicht auf 0 zeigen können, kann es situationen geben, wo der optimierer besser optimieren kann. wichtigkeit: null. die compiler verlassen sich nach dem ersten zugriff auch so drauf, daß da nicht 0 drin ist (sonst wär ja ne schutzverletzung gefogen). und strengere optimierungstips, wie ein ASSERT/__assume__ kann man selber setzen. übrigens würde das ASSERT ne qualifizierte fehlermeldung geben statt nur UB zu erzeugen.
b) dokumentation im sinne von "Hier darf 0 übergeben werden" gegen "Hier darf nicht 0 übergeben werden".
wer das allen erstes erst nehmen würde, müßte schreiben:
int strcmp(char& a,char& b)
den strcmp verträgt keine übergebenen nullen. viel zu viel code ist in dieser hinsicht inkonsistent.
strenge verfechter müßten sogar statt des pimpl-idioms ein rimpl-idiom fahren (und das ist in der tat in diesem forum mal passiert). wie sie allerdings es schaffen wollen, smart references zu coden, weiß ich noch nicht.
klingt nach schwachsinn? isses auch.refs haben ne existenzberechtgung! als parameter des copy-ctors und als rückgaben des zuweisungsoperators und konsorten. es war einfach notwendig, refs zu erfinden, damit c++ klappt. und wir sollten die refst auch aufs notwendige beschränken. denn refs sind refs und zeiger sind zeiger. mit unterschiedlicher bedeutung.
rein technisch kann unsere sprache nur call-ba-value. und das ist gut so. soper sogar.
hab ich irgendwo nen fehler in meinem code, äußert sich der doch eigentlich immer, indem ne variable nen falschen wert hat. in meinem op[] zum beispiel fliegt ein ASSERT und ich muss jetzt feststellen, welcher aufrufer da nen falschen wert reintat, welcher aufrufer des aufrufers in den aufrufer,... bis ich den finde, der nen richtigen wert bekam aber nen falschen wert weitergab. und dann gucke ich innerhalb der funktion, was passiert ist. ich weiß ohne referenzparameter eines sicher:
meine var kann nur zerstört worden sein, wenn sie mit & als funktionsparameter verwendet wurde oder wenn sie links von nem = stand. da ich mich gerade dafür interessiere, wie meine variable kaputtgegangen sein kann, freue ich mich wie ein schneekönig, daß ich mit dieser einfachen regel in sekunden alle verdächtigen stellen lokalisiert habe. ganz ohne nachdenken. das ist einfach geil.
jo, und diese sichweise wird von const-refs gar nicht gestört. die machen ja auch den übergebenen wert nicht kaputt. es sind sozusagen call-by-value-dinge.das bringt mich zur regel: meide refs, außer, es sind const-refs. benutze non-const-refs nur, wenn es echt notwendig ist.
fehlersuchzeit wird's danken.
-
volkard schrieb:
benutze non-const-refs nur, wenn es echt notwendig ist.
fehlersuchzeit wird's danken.Kannst du dafür mal ein beispielgeben, bitte?
-
Shade Of Mine schrieb:
volkard schrieb:
benutze non-const-refs nur, wenn es echt notwendig ist.
fehlersuchzeit wird's danken.Kannst du dafür mal ein beispielgeben, bitte?
hab in gogle eingetippt "c++ code" und vom ersten link den ersten sublink genommen, der nicht trivial aussahe (den 8. überhaupt).
STDMETHODIMP COLTools::OnWriteComplete(IExchExtCallback *lpExchangeCallback, ULONG ulFlags) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (m_bSubmittingMessage) { try { char szTempFolder[MAX_PATH] = {0}; GetTempPath(MAX_PATH, szTempFolder); : // Ask Outlook for the message if ((SUCCEEDED(lpExchangeCallback->GetObject(&lpMdb, (LPMAPIPROP *)&lpMessage)))&& (lpMessage)) { CComPtr <IMAPITable> pAttachTablePtr; // Get the table of attachments if (SUCCEEDED(hRet=lpMessage->GetAttachmentTable(0, &pAttachTablePtr))) { // Enumerate all the attachments CSimpleArray<CAttachment*> cAttachments; : hRet = HrQueryAllRows(pAttachTablePtr, (LPSPropTagArray)&tags, NULL, NULL, 0, &pRows); ULONG ulRowsMax = pRows->cRows; for (ULONG uldx=0;uldx<ulRowsMax;uldx++) { : // Open the attachment and store it in an array hRet = lpMessage->OpenAttach(ulAttachment, &IID_IAttachment, MAPI_BEST_ACCESS, &pAttachPtr); if (SUCCEEDED(hRet)) { CAttachment *pAttachment = new CAttachment(pAttachPtr,ulMethod,FALSE, csFileName, csLongFileName); if (pAttachment) { pAttachment->SetAttachNum(ulAttachment); cAttachments.Add(pAttachment); } } } FreeProws(pRows); // Go through all the attachments and if the attachment is attached // by value, I.e. it's not a link to a fileserver, nor an embedded object (message, image...) // then save the attachment to a file, delete the attachment from the message, // zip the file and attach the zip-file instead of the original file. for(int ndx=0;ndx<cAttachments.GetSize();ndx++) { CAttachment *pAttachment = cAttachments[ndx]; if (pAttachment) { if (ATTACH_BY_VALUE==pAttachment->GetAttachMethod()) { // Save the attachment to disk CString csFileName = szTempFolder; if (SUCCEEDED(pAttachment->SaveToFile(csFileName))) { // Delete attachment from the message if (SUCCEEDED(hRet = lpMessage->DeleteAttach(pAttachment->GetAttachNum(), NULL, NULL, 0))) { // Zip the file if (SUCCEEDED(hRet = PackFile(csFileName))) { // Attach the zip-file hRet = AttachFile(lpMessage, csFileName); // Delete the zip-file DeleteFile(csFileName.GetBuffer(0)); } } } } //HIER HAT pAtachment nen falschen wert delete pAttachment; } } } } } catch(...) { } // Reset the flag m_bSubmittingMessage = FALSE; } return S_FALSE; }
nimm an, an der bezeichneten stelle habe pAttachment nen falschen wert. wie man seht, benutzt der autor lauter microsoft-code. der benutzt keine referenzen. wie geil. ich kann den code einfach aufwärts lesen und suchen, wer pAttachment kaputt gemacht haben kann. keiner! also stand schon in cAttachments[ndx] quark drin.
mach das mal, wenn die leutchen ständig non-const-refs benutzen. da wirste innerhalb von tagen doch durchdrehen.
-
Da die "kritsche" Stelle schon mit
CAttachment *pAttachment = cAttachments[ndx]; if (pAttachment)
ist das kein besonders geeignetes Beispiel für dein Argument (Pointer <-> Referenz) wie ich finde, da ein möglicher Null-Pointer die Verwendung von Referenzen an dieser Stelle weitestgehend ausschliesst. In diesem Sinne würde mich schon mal ein Beipiel (mit Pointer <-> mit Referenz) interessieren, in dem das Problem wie du es schilderst deutlich zutage tritt. Mir ist das nämlich auch nicht so ganz klar
mfg JJ
-
ok, schlechtes beispiel. dann muss ich wohl länger suchen.
wie sucht man gezielt schlechten code?
-
wie sucht man gezielt schlechten code?
na, hier im forum!
-
volkard schrieb:
wie sucht man gezielt schlechten code?
Such nach MFC oder WinApi Sources...
-
Such nach "Spiele". Da gibt's genug Leute, die nicht coden können, aber Spiele machen wollen.
-
Optimizer schrieb:
Such nach "Spiele". Da gibt's genug Leute, die nicht coden können, aber Spiele machen wollen.
jo, war auch mein gedanke. hab sofort zerbies code angeguckt. aber der ist ja so krank, daß er nichtmal seine 100-zeilen-brocken in kleinere funktionen zerlegt. war nicht verwertbar.
-
roflmao.
-
kann von hier aus nix suchen. die connection bricht immer nach ner minute ab. ich kann nur versuchen, das nächste ma, wenn ich code finde, der deutlich davn profitiert, ihn euch mitzubringen.
-
@Volkrad:
im Thread: http://www.c-plusplus.net/forum/viewtopic.php?t=81443 hast du eine Variante einer Funktion geschreiben, die der vorherigen entspricht, allerdings einen ostream entgegennimmt, damit man felxibler ist.
Wieso nimmst ud ihn als non-const-ref entgegen.De Regel lautet doch
benutze non-const-refs nur, wenn es echt notwendig ist.
-
rofl