🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.objects
Article #4739

Re: Prawda o C++

#4739
From: Marcin 'Qrczak' Kowalczyk
Date: Tue, 19 Jan 1999 18:56
175 lines
6543 bytes
On 19 Jan 1999, Sektor van Skijlen wrote:

> : Nieprawda. Referencja to jest praktycznie to samo co wskaźnik. Różni się
> : wyłącznie składnią, przy czym niektóre operacje na wskaźnikach nie mają
> : odpowiedników na referencjach.
> 
> Masz cos sensownego na poparcie tych glupot ?

Tak. Tego typu twierdzenie, jeśli jest fałszywe, można obalić przez
podanie kontrprzykładu. Proszę więc o kawałek kodu używającego referencji,
którego nie da się w trywialny sposób przerobić na wskaźniki.

Prawdę mówiąc sam znalazłem taki przykład: konstruktor kopiujący. Wynika
to z tego, że C++ używa go w pewnych sytuacjach niejawnie i oczekuje
konkretnej formy nagłówka. Przyznaję, tutaj jest to nieprawda. Wynika to
jednak nie z tego, że analogiczny kod na wskaźnikach robiłby co innego,
tylko z tego, że C++ oczekuje konkretnej składni do niejawnego użycia
w specjalny sposób.

> :> ale np. tutaj juz nie:
> :> 
> :> {
> :> 	CosTam* nic = new CosTam;
> :> 
> :> 	CosTam& rnic = *nic;
> :> 
> :> 	rnic = { 2, 65 };
> :> }
> 
> : To się przede wszystkim nie skompiluje (błąd składni w ostatnim
> : przypisaniu - napis { 2, 65 } nie jest poprawnie zbudowanym wyrażeniem).
> 
> : Można to uratować następującym rozszerzeniem gcc:
> :   rnic = (CosTam) { 2, 65 };
> 
> Ok, przyznaje sie. Zamienmy to na:
> 
> 	CosTam dwa( 5, 5 ); // powiedzmy, ze to ma taki konstruktor
> 
> 	rnic = dwa;

I gdzie tu jest przykład, że referencje istotnie różnią się od wskaźników?
Na wskaźnikach wyglądałoby to tak:
  CosTam *rnic = nic;
  ...
  *rnic = dwa;

> : i jest to taka sama sytuacja jak poprzednio. Referencja może być
> : zaimplementowana jako wskaźnik i prawdę mówiąc nie widzę innego sensownego
> : rozwiązania.
> 
> Niestety kompletna bzdura, kolego. Zmiennej rnic w ogole nie bedzie. Zamiast
> tego, kompilator to przypisanie zamieni na rownowazne:
> 
> 	*nic = dwa;

[qrczak ~]$ cat ref1.cc
#include <iostream.h>
class CosTam
{
public:
    int i, k;
    CosTam (int ii, int kk) : i (ii), k (kk) {}
};
main()
{
    CosTam *nic = new CosTam (0, 0);
    CosTam &rnic = *nic;
    CosTam dwa (5, 5);
    nic = new CosTam (9, 9);
    rnic = dwa;
    cout << rnic.i << dwa.i << nic->i << "\n";
    return 0;
}
[qrczak ~]$ ./ref1
559
[qrczak ~]$ g++ --version
egcs-2.91.60

Jeśli kompilator zamienił to przypisania na *nic = dwa, to jakim cudem
wartości *nic i dwa są potem różne?

> Mozliwe. Sprawdzilem to dosc szczegolowo i faktycznie, nie udalo mi
> sie jak na razie zrobic takiego przykladu, w ktorym zmienna
> referencyjna bylaby "optimized away" (co nie znaczy, ze takich
> przypadkow nie ma).

To się ma prawo zdarzyć i przy wskaźnikach, jeśli kompilator jest sprytny
i potrafi sprawdzić, na co wskaźnik wskazuje:

[qrczak ~]$ cat ref2.cc
int kura;
main()
{
    int *kogut = &kura;
    *kogut = 7;
    return 0;
}
[qrczak ~]$ g++ -S -O3 ref2.cc
[qrczak ~]$ less ref2.s
[...]
main:
.LFB1:
        pushl %ebp
.LCFI0:
        movl %esp,%ebp
.LCFI1:
        movl $7,kura
        xorl %eax,%eax
        leave
        ret
[...]

> A teraz maly tescik dla grupowiczow.
> 
> Zmienna referencyjna to zmienna, jak kazda inna, tak ?
> Operator & uzyskuje adres zmiennej, tak ?
> 
> No wiec prosze powiedziec, co zwroci wyrazenie &ref, gdzie ref jest dowolna
> zmienna referencyjna ?

Wskaźnik na obiekt wskazywany przez ref.

Nie twierdziłem nigdy, że "to jest zmienna jak każda inna", co by miało
pewnie znaczyć, że nie ma własności wyróżniającej referencje spośród
innych typów. Są takie własności. Ale co chcemy tutaj pokazać?

> Jesli zmienne referencyjne naleza do pol, to niestety jest to dla mnie troche
> dziwne. Bo jezeli mamy taka strukture:
> 
> struct Krotka
> {
> 	int a;
> 	const int d = 2;
> };
> 
> to pole d niby nalezy do pol struktury, a jednak struktura ma te sama
> wielkosc, co int...

Ano ma. Ale gdzie tu mamy referencje?

> To pierwsze zreszta, to tylko rozszerzenie GCC, standard zabrania
> takich inicjalizacji...

W gcc też jest niemile widziane:

ref3.cc:5: warning: ANSI C++ forbids initialization of const member `d'
ref3.cc:5: warning: making `d' static

> Szczerze mowiac, nie rozumiem, dlaczego nie moznaby zrobic tego tak, zeby
> zmienna nie istniala.

W którym przypadku?

> W koncu przeciez tak jak stala zmienna wskaznikowa, jak i wartosc
> stala, jak tez i referencja nie maja mozliwosci przypisywania, totez
> nie jest istotne, GDZIE te zmienne sa umieszczone, czy naleza do
> struktury, czy nie (przypomne, ze np. stale statyczne sa umieszczane w
> segmencie kodu). W szczegolnych przypadkach mogloby ich w ogole nie
> byc.

Jest istotne. Bo jeśli napiszesz:

int &f();
int &a = f();

to byłoby bez sensu, żeby przy każdym odwołaniu do zmiennej a była
wywoływana funkcja f(). Więc wartość a musi być gdzieś zapamiętana.
Jest zapamiętana tam, gdzie byłaby zapamiętana, gdyby nie była referencją.

-- 
 __("<    Marcin Kowalczyk * qrczak@knm.org.pl http://kki.net.pl/qrczak/
 \__/       GCS/M d- s+:-- a21 C+++>+++$ UL++>++++$ P+++ L++>++++$ E->++
  ^^                W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP->+ t
QRCZAK                  5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-
Technical Details
Message-ID: <Pine.LNX.4.05.9901191914060.379-100000@qrnik.knm.org.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!mat.uni.torun.pl!news.nask.pl!orion.cst.tpsa.pl!news.tpnet.pl!not-for-mail
References: <77o3bl$j0q$1@polonez.man.lodz.pl> <369FDDCE.7B94748A@interdata.com.pl> <77q41i$j7f$1@polonez.man.lodz.pl> <wU3o2.25549$U1.4744058@news.tpnet.pl> <77qi2q$42a$1@polonez.man.lodz.pl> <77qk38$ken$1@zeus.polsl.gliwice.pl> <77vn97$j3l$1@polonez.man.lodz.pl> <Pine.LNX.4.05.9901182050560.542-100000@qrnik.knm.org.pl> <78256q$9l8$5@polonez.man.lodz.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!mat.uni.torun.pl!news.nask.pl!orion.cst.tpsa.pl!news.tpnet.pl!not-for-mail
From: Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl>
Newsgroups: pl.comp.lang.c,pl.comp.objects
Subject: Re: Prawda o C++
Organization: Klub Nieszkodliwych Manjaków
Lines: 176
Message-ID: <Pine.LNX.4.05.9901191914060.379-100000@qrnik.knm.org.pl>
References: <77o3bl$j0q$1@polonez.man.lodz.pl> <369FDDCE.7B94748A@interdata.com.pl> <77q41i$j7f$1@polonez.man.lodz.pl> <wU3o2.25549$U1.4744058@news.tpnet.pl> <77qi2q$42a$1@polonez.man.lodz.pl> <77qk38$ken$1@zeus.polsl.gliwice.pl> <77vn97$j3l$1@polonez.man.lodz.pl> <Pine.LNX.4.05.9901182050560.542-100000@qrnik.knm.org.pl> <78256q$9l8$5@polonez.man.lodz.pl>
Mime-Version: 1.0
In-Reply-To: <78256q$9l8$5@polonez.man.lodz.pl>
Date: Tue, 19 Jan 1999 18:56:40 GMT
NNTP-Posting-Host: 195.116.251.39
X-Complaints-To: abuse@tpsa.pl
X-Trace: news.tpnet.pl 916772200 195.116.251.39 (Tue, 19 Jan 1999 19:56:40 MET DST)
NNTP-Posting-Date: Tue, 19 Jan 1999 19:56:40 MET DST
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit