|
| call by reference vs. pointers Fra : Henrik Koksby Hansen |
Dato : 09-06-02 12:57 |
|
Hej igen i gruppen.
Er der nogen, der kan give en god forklaring på forskellen - fordele
og/eller ulemper - mellem call by reference og call by reference with
pointer arguments.
Umiddelbart kan jeg ikke gennemskue den store forskel.
MVH
Henrik
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 13:21 |
|
Henrik Koksby Hansen wrote:
> Er der nogen, der kan give en god forklaring på forskellen - fordele
> og/eller ulemper - mellem call by reference og call by reference with
> pointer arguments.
I den genererede kode er der ingen forskel ud over, at du i den kaldte
funktion kan give dig til at regne på pointere (*p++, f.eks) med ikke
på referencer.
> Umiddelbart kan jeg ikke gennemskue den store forskel.
Der er heller ikke nogen "stor" forskel. Men der er forskellige kon-
ventioner for hvornår man bruger det ene og hvornår man bruger det
andet.
F.eks bruger nogen pointer overførsel til at indikere, at den kaldte
funktion skal tage ejerskab over objektet:
void indsæt_i_container(Some* objekt);
....mens reference-overførsel bruges som almindelig parameteroverfør-
sel men uden en dyr kopiering:
void inverter_matrix(MegaStorMatrix&);
Brugen af denne konvention (som kun er een blandt flere) forplumres
dog af, at alle gamle standard C rutiner konsekvent anvender pointer-
overførsel i stedet for reference-overførsel.
-Claus
| |
Bertel Lund Hansen (09-06-2002)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 09-06-02 14:04 |
|
Claus Rasmussen skrev:
>Brugen af denne konvention (som kun er een blandt flere) forplumres
>dog af, at alle gamle standard C rutiner konsekvent anvender pointer-
>overførsel i stedet for reference-overførsel.
.... hvilket stort set skyldes at det andet ikke er tilladt.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 21:19 |
|
Bertel Lund Hansen <nospam@lundhansen.dk> skrev:
> Claus Rasmussen skrev:
>
>>Brugen af denne konvention (som kun er een blandt flere) forplumres
>>dog af, at alle gamle standard C rutiner konsekvent anvender pointer-
>>overførsel i stedet for reference-overførsel.
>
> ... hvilket stort set skyldes at det andet ikke er tilladt.
I C findes begrebet reference-overførsel ikke. I stedet bruger man
(eller bør man bruge) const-pointere som argumenter når modtageren
ikke skal ændre i det som der peges på. F.eks. ser prototypen til
strcpy() i string.h sådan her ud:
char *strcpy(char *dest, const char *src);
Det er vigtigt at huske at bruge const når et argument ikke ændres.
Det forøger oversætterens muligheder for optimering, men meget
vigtigere end det er at det gør programmet lettere at læse og få
overblik over, og kan hjælpe med at finde fejl.
| |
Per Abrahamsen (14-06-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 14-06-02 14:44 |
|
Byrial Jensen <bjensen@nospam.dk> writes:
> Det er vigtigt at huske at bruge const når et argument ikke ændres.
> Det forøger oversætterens muligheder for optimering,
Gør det? Man skal huske på at "const" kun betyder at en objekt ikke
må ændres _gennem dette navn_.
F.eks.
double x + 1.0:
const double* y = &x;
printf ("%g\n", *y);
x = 2.0;
printf ("%g\n", *y);
her ændrer *y sig i de to udskrifter, selv om den er erklæret const.
Så vidt jeg lige kan regne ud så fortæller "const" kun compileren
noget den i forvejen godt selv kan regne ud, i hvert fald for
funktionsargumenter. For globale variable kan det godt være en hjælp.
> men meget vigtigere end det er at det gør programmet lettere at læse
> og få overblik over, og kan hjælpe med at finde fejl.
Helt enig.
| |
Byrial Jensen (14-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 14-06-02 16:20 |
|
Per Abrahamsen <abraham@dina.kvl.dk> skrev:
> Byrial Jensen <bjensen@nospam.dk> writes:
>
>> Det er vigtigt at huske at bruge const når et argument ikke ændres.
>> Det forøger oversætterens muligheder for optimering,
>
> Gør det? Man skal huske på at "const" kun betyder at en objekt ikke
> må ændres _gennem dette navn_.
Ja. En oversætter vil ofte kunne udelukke at en kaldt funktion har
andre muligheder for at tilgå et objekt end gennem en given pointer
til const.
I programmet herunder har func() ingen mulighed for at ændre tal,
og if-sætningen kan derfor helt bort-optimeres.
#include <stdio.h>
extern void func (const int *p);
int main()
{
int start = 87;
int tal = start;
func (&tal);
if (tal != start)
printf ("Tal ændret til %d\n", tal);
return 0;
}
| |
Torben W. Hansen (02-07-2002)
| Kommentar Fra : Torben W. Hansen |
Dato : 02-07-02 20:46 |
|
Undskyld - men jeg snublede over denne tråd...
> Gør det? Man skal huske på at "const" kun betyder at en objekt ikke
> må ændres _gennem dette navn_.
>
> F.eks.
>
> double x + 1.0:
> const double* y = &x;
> printf ("%g\n", *y);
> x = 2.0;
> printf ("%g\n", *y);
>
> her ændrer *y sig i de to udskrifter, selv om den er erklæret const.
Jeg er ikke nogen hard core guru og spørger derfor måske lidt dumt til
erklæringen ovenfor:
Er det y (pointeren) eller er det *y (indholdet af det pointer y peger på)
som er konstant (const) ?
--
med venlig hilsen
Torben W. Hansen
| |
Byrial Jensen (02-07-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 02-07-02 21:51 |
|
Torben W. Hansen <mail@ins-intersoft.com> skrev:
> Undskyld - men jeg snublede over denne tråd...
>
>> const double* y = &x;
>
> Er det y (pointeren) eller er det *y (indholdet af det pointer y peger på)
> som er konstant (const) ?
Det er det som y peger på, som er konstant. Hvis pointeren i sig
selv skal være konstant, er erklæringen:
double* const y = &x;
| |
Torben W. Hansen (03-07-2002)
| Kommentar Fra : Torben W. Hansen |
Dato : 03-07-02 16:08 |
|
Tak for dit svar B. Jensen...
men hvad betyder så dette ?
double const *y = &x;
Det er ikke fordi jeg ikke selv "gider" at undersøge det, men jeg synes ikke
at definition af 'const' fremgår særlig tydeligt i Kernighan & Ritchie 2'nd
udg. side 223, A8.2
med venlig hilsen
Torben W. Hansen
"Byrial Jensen" <bjensen@nospam.dk> skrev i en meddelelse
news:slrnai41pm.10n.bjensen@ask.ask...
> Torben W. Hansen <mail@ins-intersoft.com> skrev:
> > Undskyld - men jeg snublede over denne tråd...
> >
> >> const double* y = &x;
> >
> > Er det y (pointeren) eller er det *y (indholdet af det pointer y peger
på)
> > som er konstant (const) ?
>
> Det er det som y peger på, som er konstant. Hvis pointeren i sig
> selv skal være konstant, er erklæringen:
>
> double* const y = &x;
| |
Jonas Meyer Rasmusse~ (03-07-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 03-07-02 16:31 |
|
"Torben W. Hansen" <mail@ins-intersoft.com> wrote in message
news:afv4bu$2pnf$1@news.cybercity.dk...
> Tak for dit svar B. Jensen...
>
> men hvad betyder så dette ?
>
> double const *y = &x;
Det som peges på er const.
Det der er afgørende er på hvilken side af *'en const erklæringen
står.
til venstre -> det som peges på er const
til højre -> pegeren er const
mvh Jonas
| |
Torben W. Hansen (03-07-2002)
| Kommentar Fra : Torben W. Hansen |
Dato : 03-07-02 17:09 |
|
Tak Jonas - for dit meget hurtige svar...
Iflg. Byrial:
const double* y = &x; (Det er det som y peger på, som er konstant)
double* const y = &x; (Hvis pointeren i sig selv skal være konstant)
Iflg. dig (Jonas):
double const *y = &x; (Det som peges på er const.)
Betyder det så at erklæringerne nedenfor er identiske ?
const double* y = &x; og double const *y = &x;
--
med venlig hilsen
Torben W. Hansen
| |
Jonas Meyer Rasmusse~ (03-07-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 03-07-02 17:36 |
|
> Betyder det så at erklæringerne nedenfor er identiske ?
>
> const double* y = &x; og double const *y = &x;
Ja, det er korrekt
Jonas
| |
Byrial Jensen (03-07-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 03-07-02 17:49 |
|
Torben W. Hansen <mail@ins-intersoft.com> skrev:
> Tak for dit svar B. Jensen...
>
> men hvad betyder så dette ?
>
> double const *y = &x;
Det betyder det samme som
const double *y = &x;
> Det er ikke fordi jeg ikke selv "gider" at undersøge det, men jeg synes ikke
> at definition af 'const' fremgår særlig tydeligt i Kernighan & Ritchie 2'nd
> udg. side 223, A8.2
(Afsnit A8.2 er på side 211 i min udgave. Er det den danske
oversættelse du har?)
Både double og const er "declaration-specifiers" (afsnit A8), og
sådanne må i princippet komme i vilkårlig rækkefølge uden at
betydningen ændrer sig. Man kan således frit vælge at skrive
f.eks.:
static const int d1;
static int const d2;
const static int d3;
const int static d4;
int const static d5;
int static const d6;
long volatile int const long extern unsigned bad;
Jeg vil dog stærkt anbefale at bruge den sædvanligt brugte
rækkefølge som er: Først højst én "storage-class-specifier"
(typedef, extern, static, auto, register), efterfulgt af et antal
"type-qualifier"e (const, restrict, volatile) og til sidst mindst
én "type-specifier".
Erklæringer af pointere er forklaret i afsnit A8.6.1 som har
eksempler med både en konstant pointer og en pointer til et
konstant objekt.
| |
Torben W. Hansen (03-07-2002)
| Kommentar Fra : Torben W. Hansen |
Dato : 03-07-02 18:17 |
|
> (Afsnit A8.2 er på side 211 i min udgave. Er det den danske
> oversættelse du har?)
Ja,
> Både double og const er "declaration-specifiers" (afsnit A8), og
> sådanne må i princippet komme i vilkårlig rækkefølge uden at
> betydningen ændrer sig. Man kan således frit vælge at skrive
> f.eks.:
>
> static const int d1;
> static int const d2;
> const static int d3;
> const int static d4;
> int const static d5;
> int static const d6;
> long volatile int const long extern unsigned bad;
>
> Jeg vil dog stærkt anbefale at bruge den sædvanligt brugte
> rækkefølge som er: Først højst én "storage-class-specifier"
> (typedef, extern, static, auto, register), efterfulgt af et antal
> "type-qualifier"e (const, restrict, volatile) og til sidst mindst
> én "type-specifier".
>
> Erklæringer af pointere er forklaret i afsnit A8.6.1 som har
> eksempler med både en konstant pointer og en pointer til et
> konstant objekt.
Tak for den uddybende forklaring. Jeg vil forsøge at nærlæse min danske
udgave af K&R.
--
med venlig hilsen
Torben W. Hansen
| |
Torben W. Hansen (03-07-2002)
| Kommentar Fra : Torben W. Hansen |
Dato : 03-07-02 22:44 |
|
> Erklæringer af pointere er forklaret i afsnit A8.6.1 som har
> eksempler med både en konstant pointer og en pointer til et
> konstant objekt.
Jeg har nu nærlæst min danske udgave af K&R og ganske som du nævner er der
et udmærket eksempel i A8.6.1.
Tak...
--
med venlig hilsen
Torben W. Hansen
| |
Per Abrahamsen (14-06-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 14-06-02 16:40 |
|
Byrial Jensen <bjensen@nospam.dk> writes:
> Ja. En oversætter vil ofte kunne udelukke at en kaldt funktion har
> andre muligheder for at tilgå et objekt end gennem en given pointer
> til const.
Ah, ja, jeg tænkte kun på den kaldte funktion, ikke kalderen.
> I programmet herunder har func() ingen mulighed for at ændre tal,
> og if-sætningen kan derfor helt bort-optimeres.
Er du sikker? Jeg mindes at have læst at
void func (const int* p)
{
int* q = (int*) p;
*q = 7;
}
er veldefineret, forudsat at p ikke peger på et konstant objekt.
> #include <stdio.h>
> extern void func (const int *p);
> int main()
> {
> int start = 87;
> int tal = start;
>
> func (&tal);
>
> if (tal != start)
> printf ("Tal ændret til %d\n", tal);
> return 0;
> }
| |
Byrial Jensen (14-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 14-06-02 20:20 |
|
Per Abrahamsen <abraham@dina.kvl.dk> skrev:
> Byrial Jensen <bjensen@nospam.dk> writes:
>
>> Ja. En oversætter vil ofte kunne udelukke at en kaldt funktion har
>> andre muligheder for at tilgå et objekt end gennem en given pointer
>> til const.
>
> Ah, ja, jeg tænkte kun på den kaldte funktion, ikke kalderen.
>
>> I programmet herunder har func() ingen mulighed for at ændre tal,
>> og if-sætningen kan derfor helt bort-optimeres.
>
> Er du sikker? Jeg mindes at have læst at
>
> void func (const int* p)
> {
> int* q = (int*) p;
> *q = 7;
> }
>
> er veldefineret, forudsat at p ikke peger på et konstant objekt.
Hmm...
Ja, strengt taget har du vist ret. Det gælder at:
A pointer to an object [...] type may be converted to a pointer
to a different object [...] type. [When the resulting pointer
is] converted back again, the result shall compare equal to the
original pointer. (C99, §6.3.2.3#7).
Så hvis p oprindeligt stammer fra en pointer af type "int *" som
blev konverteret til type "const int *" ved funktionskaldet, er det
veldefineret at konvertere den tilbage og bruge den som "int *".
Så det er alligevel ikke korrekt at optimere ud fra en antagelse om
at kaldte funktioner ikke ændrer hvad deres argumenter af type
pointer til const objekt peger på.
Men jeg ville intet have imod en oversætter som kunne sættes til at
optimere ud fra en sådan antagelse. Det ville nemlig være galimatias
at lave en sådan konvertering af "pointer til const"-argumenter da
det:
- Ville give udefineret adfærd hvis pointeren peger på et const
objekt (hvilket funktionen ikke kan vide eller undersøge om den
gør).
- Bryder alle berettigede forventninger til funktionens opførsel.
| |
Byrial Jensen (14-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 14-06-02 21:44 |
|
Byrial Jensen <bjensen@nospam.dk> skrev:
> Så det er alligevel ikke korrekt at optimere ud fra en antagelse om
> at kaldte funktioner ikke ændrer hvad deres argumenter af type
> pointer til const objekt peger på.
Ved nærmere eftertanke vil jeg fastholde min oprindelige påstand om
at man kan optimere på grund af const-erklæringer. Mit første
eksempel var forkert, men det kan let repareres ved at tilføje
endnu en const-erklæring:
#include <stdio.h>
extern void func (const int *p);
int main()
{
int start = 87;
const int tal = start; /* const tilføjet her */
func (&tal);
if (tal != start)
printf ("Tal ændret til %d\n", tal);
return 0;
}
Nu kan if-sætningen optimeres væk uden problemer. Det kunne den
ikke uden const-erklæringerne af tal og *p.
| |
Bjarke Dahl Ebert (15-06-2002)
| Kommentar Fra : Bjarke Dahl Ebert |
Dato : 15-06-02 10:54 |
|
"Byrial Jensen" <bjensen@nospam.dk> wrote in message
news:slrnagklhf.1rb.bjensen@ask.ask...
> int start = 87;
> const int tal = start; /* const tilføjet her */
>
> func (&tal);
>
> if (tal != start)
> printf ("Tal ændret til %d\n", tal);
> return 0;
> }
>
> Nu kan if-sætningen optimeres væk uden problemer. Det kunne den
> ikke uden const-erklæringerne af tal og *p.
Optimeringen er vel korrekt ifølge standarden, men er der virkelig nogen
compilere der kan finde ud af den optimering?
Bjarke
| |
Byrial Jensen (16-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 16-06-02 14:06 |
|
Bjarke Dahl Ebert <bebert@worldonline.dk> skrev:
> Optimeringen er vel korrekt ifølge standarden, men er der virkelig nogen
> compilere der kan finde ud af den optimering?
Jeg synes ikke at det virker urealistisk at der skulle findes
oversættere som kan finde ud af det.
Hvis jeg laver en lille forenkling ved sætte tal til 0 i stedet for
87 som her nedenfor, klarer min gcc det fint.
#include <stdio.h>
extern void func (const int *p);
int main()
{
const int tal = 0;
func (&tal);
if (tal)
printf ("Tal ændret til %d\n", tal);
return 0;
}
| |
Bjarke Dahl Ebert (15-06-2002)
| Kommentar Fra : Bjarke Dahl Ebert |
Dato : 15-06-02 10:52 |
|
"Byrial Jensen" <bjensen@nospam.dk> wrote in message
news:slrnagkgi0.1k7.bjensen@ask.ask...
[cast'e const væk]
> Men jeg ville intet have imod en oversætter som kunne sættes til at
> optimere ud fra en sådan antagelse. Det ville nemlig være galimatias
> at lave en sådan konvertering af "pointer til const"-argumenter da
> det:
>
> - Ville give udefineret adfærd hvis pointeren peger på et const
> objekt (hvilket funktionen ikke kan vide eller undersøge om den
> gør).
>
> - Bryder alle berettigede forventninger til funktionens opførsel.
Der kan alligevel være tilfælde hvor man er interesseret i at cast'e en
const væk (eller const_cast'e i C++).
Specielt hvis man begynder at have flere niveauer af indirection.
const Foo* find_foo(const Foo**);
Denne funktion kan man kalde med et array af pointere til const Foo, og
funktionen finder så en af dem. Denne returnerede Foo* er selvfølgelig igen
const.
Men hvis kalderen står med et array "Foo**", så kan det ikke
auto-konverteres til "const Foo**".
Der gælder følgende implicitte konverteringer:
(1) Foo* -->const Foo* JA
(2) Foo** --> const Foo** NEJ (med god grund!)
(3) Foo** --> const Foo* const* JA
I ovenstående find_foo har man derfor problemer. Der er følgende muligheder:
- Behold funktionen, og lad kalderen const_cast'e hvis han har en "Foo**".
- Lav funktionen om (fjern 'const'), og lad kalderen const_cast'e hvis han
har en "const Foo**"
- Lav to forskellige funktioner, som kun adskiller sig ved deres constness!
(Ufedt)
Så konklusionen er: Der *er* tilfælde hvor man bliver nødt til at
const_cast'e, hvor man VED at det er lovligt, men det statiske typesystem er
ikke smart nok til at indse det - så må man "hjælpe" med en cast. Fx. ved
kald til find_foo, ved man at det er OK at cast'e argumentet.
Bjarke
| |
Byrial Jensen (16-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 16-06-02 14:06 |
|
Bjarke Dahl Ebert <bebert@worldonline.dk> skrev:
> Der kan alligevel være tilfælde hvor man er interesseret i at cast'e en
> const væk (eller const_cast'e i C++).
> Specielt hvis man begynder at have flere niveauer af indirection.
>
> const Foo* find_foo(const Foo**);
>
> Denne funktion kan man kalde med et array af pointere til const Foo, og
> funktionen finder så en af dem. Denne returnerede Foo* er selvfølgelig igen
> const.
En sådan findefunktion burde nok erklæres som
const Foo* find_foo(const Foo* const*);
da man normalt ikke vil forvente at den ændrer i arrayet af
pointere til const Foo.
> Men hvis kalderen står med et array "Foo**", så kan det ikke
> auto-konverteres til "const Foo**".
Korrekt.
> I ovenstående find_foo har man derfor problemer. Der er følgende muligheder:
> - Behold funktionen, og lad kalderen const_cast'e hvis han har en "Foo**".
> - Lav funktionen om (fjern 'const'), og lad kalderen const_cast'e hvis han
> har en "const Foo**"
> - Lav to forskellige funktioner, som kun adskiller sig ved deres constness!
> (Ufedt)
Her ville jeg vælge den første mulighed.
> Så konklusionen er: Der *er* tilfælde hvor man bliver nødt til at
> const_cast'e, hvor man VED at det er lovligt, men det statiske typesystem er
> ikke smart nok til at indse det - så må man "hjælpe" med en cast. Fx. ved
> kald til find_foo, ved man at det er OK at cast'e argumentet.
Det har du ret i. Men den eksplicitte typekonvertering (castningen)
kan begrænses til at tilføje ekstra "const" til argumenter ved
funktionskald, og fjerne det igen fra returværdien.
#include <stdio.h>
typedef int Foo;
#define ELEMENTER(x) (sizeof(x)/sizeof(*x))
const Foo* find_foo(const Foo * const * array, size_t size, Foo foo)
{
size_t i;
for (i = 0 ; i < size ; i ++)
if (*array[i] == foo)
return array[i];
return NULL;
}
int main()
{
/* Vi behøver nogle Foo-objekter */
Foo f1 = 16, f2 = 56, f3 = 28;
const Foo c1 = 44, c2 = 25, c3 = 67;
/* Og nogle arrays af Foo-pointere */
Foo *farray[] = { &f1, &f2, &f3 };
const Foo *carray[] = { &c1, &c2, &c3 };
Foo *fp = (Foo *)find_foo ((const Foo **)farray, ELEMENTER(farray), 56);
const Foo *cp = find_foo (carray, ELEMENTER(carray), 67);
// ...
return 0;
}
| |
Bjarke Dahl Ebert (16-06-2002)
| Kommentar Fra : Bjarke Dahl Ebert |
Dato : 16-06-02 22:12 |
|
"Byrial Jensen" <bjensen@nospam.dk> wrote:
> Bjarke Dahl Ebert <bebert@worldonline.dk> skrev:
> > Specielt hvis man begynder at have flere niveauer af indirection.
> > const Foo* find_foo(const Foo**);
> En sådan findefunktion burde nok erklæres som
> const Foo* find_foo(const Foo* const*);
>
> da man normalt ikke vil forvente at den ændrer i arrayet af
> pointere til const Foo.
Jep, lige præcis. Jeg kom i tanke om det efter at have sendt mailen .
Man kunne finde et bedre eksempel, hvor funktionen faktisk ændrer pointerne,
men ikke objekterne. Selvom det var et dårligt eksempel, viser det stadig at
der sommetider er brug for const_cast (eller i C: at cast'e const til og
fra).
Det var som svar på en generel påstand om at man ikke skulle const_cast'e
fordi man ikke kan vide om man faktisk peger på en const.
Mvh. Bjarke
| |
Per Abrahamsen (17-06-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 17-06-02 17:57 |
|
Byrial Jensen <bjensen@nospam.dk> writes:
> #include <stdio.h>
> extern void func (const int *p);
> int main()
> {
> const int tal = 0;
>
> func (&tal);
>
> if (tal)
> printf ("Tal ændret til %d\n", tal);
> return 0;
> }
Til gengæld klarer den også nedenstående fint, så jeg vil tro at
optimeringen skyldes at GCC har lov til at antage at et objekt der er
erklæret const virkelig er const. Uanset hvad man gør ved det.
#include <stdio.h>
extern void fonc (int *p);
int main()
{
const int tal = 0;
fonc ((int*) &tal);
if (tal)
printf ("Tal ændret til %d\n", tal);
return 0;
}
| |
Per Abrahamsen (04-07-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 04-07-02 12:14 |
|
Byrial Jensen <bjensen@nospam.dk> writes:
> Jeg vil dog stærkt anbefale at bruge den sædvanligt brugte
> rækkefølge som er: Først højst én "storage-class-specifier"
> (typedef, extern, static, auto, register), efterfulgt af et antal
> "type-qualifier"e (const, restrict, volatile) og til sidst mindst
> én "type-specifier".
Jeg har set en del anbefale
storage-class-specifier type-specifier type-qualifier
fordi det gør reglen for hvad type-qualifier henviser til lettere:
Det henviser altid til det der kommer før.
Altså
int const *const
læst bagfra = en kontant pointer til en kontant int.
Personligt bruger jeg dog rækkefølge du anbefaler, fordi den er mest
almindelig.
| |
Jonas Meyer Rasmusse~ (09-06-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 09-06-02 13:50 |
|
"Henrik Koksby Hansen" <koksby@elektronik.dk> wrote in message
news:gig6guotgq7gj32nanethd053l6889ejav@4ax.com...
> Hej igen i gruppen.
>
> Er der nogen, der kan give en god forklaring på forskellen - fordele
> og/eller ulemper - mellem call by reference og call by reference with
> pointer arguments.
>
> Umiddelbart kan jeg ikke gennemskue den store forskel.
Nej, ikke umiddelbart, men der _er_ der.
Referencer har to egenskaber:
-En reference referer _altid_ til det samme objekt, det objekt reference er
intialiseret med (assignment til en reference, virker som assignment til det
objekt der referes til)
-En reference referer _altid_ til et objekt.
dvs at du _skal initialiser dine referencer
Foo& foo = enFoo;
er korrekt, og
Foo& foo;
er ukorrekt, og burde give en oversætterfejl.
Pointers derimod
-behøver ikke referere til noget objekt(uinitialiserede pointers, eller
0-pointers)
-pointers kan godt sættes til at pege til andre objekter(du tildeler bare
til pointer variablen)
mvh Jonas
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 14:08 |
|
Jonas Meyer Rasmussen wrote:
> -En reference referer _altid_ til et objekt.
Nej.
void f(int&);
int main() {
f(*(int*)0);
}
Den slags er af og til nyttigt.
-Claus
| |
Jonas Meyer Rasmusse~ (09-06-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 09-06-02 14:19 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote in message
news:advjut$9c9$1@sunsite.dk...
> Jonas Meyer Rasmussen wrote:
>
> > -En reference referer _altid_ til et objekt.
>
> Nej.
>
> void f(int&);
>
> int main() {
> f(*(int*)0);
> }
>
> Den slags er af og til nyttigt.
Scott Meyers skriver at resultatet af dette er 'undefined behavior', og
jeg antager at han har det fra C++ standarden, da jeg ikke selv har den, kan
jeg desværre
ikke verificere det.
Hvorfor skulle det være nyttigt?
Og hvis resultatet af ovenstående er udefineret, så er det vel værd at huske
på,
at en oversætning der går igang med at formattere samtlige harddiske den kan
få fingrene
i er en gyldig oversætning...
Hvilket efter min mening skulle være rigeligt grund til at lade være med at
benytte den slags snask.
Desuden er hele pointen med referencer jo også, at _hvis_ du har brug for at
kunne referere til ingenting, så brug pointere?
Sværere er det vel ikke?
Jonas
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 14:29 |
|
Jonas Meyer Rasmussen wrote:
> Hvorfor skulle det være nyttigt?
Fordi du kan komme i situationer, hvor en klasse/funktion _vil_ have et
objekt, men du har ikke noget, at give den. Imidlertid kan du se, at
dette objekt aldrig vil blive tilgået, og så kan du nøjes med at stikke
den et dummy objekt.
[...]
> Desuden er hele pointen med referencer jo også, at _hvis_ du har brug for
> at kunne referere til ingenting, så brug pointere?
Med mindre du arbejder op imod et library, der forventer en reference.
-Claus
| |
Jonas Meyer Rasmusse~ (09-06-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 09-06-02 14:48 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote in message
news:advl68$iou$1@sunsite.dk...
> Jonas Meyer Rasmussen wrote:
>
> > Hvorfor skulle det være nyttigt?
>
> Fordi du kan komme i situationer, hvor en klasse/funktion _vil_ have et
> objekt, men du har ikke noget, at give den. Imidlertid kan du se, at
> dette objekt aldrig vil blive tilgået, og så kan du nøjes med at stikke
> den et dummy objekt.
Så burde funktionen have taget en pointer som argument.. de tillader jo at
have 0-referencer.. det gælder vel om at anvende sproget som det er designet
til?
> [...]
>
> > Desuden er hele pointen med referencer jo også, at _hvis_ du har brug
for
> > at kunne referere til ingenting, så brug pointere?
>
> Med mindre du arbejder op imod et library, der forventer en reference.
Så er det vel et skidt designet library...
Eller også har designerne ikke været ordentligt bekendt med sproget.
Det er jo ikke for sjov at compileren brokker sig når man skriver
int& a;
og så er det vel heller ikke for sjov at det er defineret som udefineret
opførsel, når man
laver det lille snydeteknik du viste?
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 15:02 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote
> Jonas Meyer Rasmussen wrote:
>
> > Hvorfor skulle det være nyttigt?
>
> Fordi du kan komme i situationer, hvor en klasse/funktion _vil_ have et
> objekt, men du har ikke noget, at give den. Imidlertid kan du se, at
> dette objekt aldrig vil blive tilgået, og så kan du nøjes med at stikke
> den et dummy objekt.
>
Nej, så er der et problem et andet sted - f.eks. i funktionens design.
> [...]
>
> > Desuden er hele pointen med referencer jo også, at _hvis_ du har brug
for
> > at kunne referere til ingenting, så brug pointere?
>
> Med mindre du arbejder op imod et library, der forventer en reference.
>
Undefined behaviour.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (09-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 09-06-02 14:59 |
|
Jonas Meyer Rasmussen wrote:
> Scott Meyers skriver at resultatet af dette er 'undefined behavior', og
> jeg antager at han har det fra C++ standarden, da jeg ikke selv har den, kan
> jeg desværre
> ikke verificere det.
Det står specifikt i §8.3.2.4:
"Note: in particular, a null reference cannot exist in a welldefined
program, because the only way to create such a reference would be to
bind it to the "object" obtained by dereferencing a null pointer, which
causes undefined behavior."
Ivan Johansen
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 15:05 |
|
Ivan Johansen wrote:
> "Note: in particular, a null reference cannot exist in a welldefined
> program, because the only way to create such a reference would be to
> bind it to the "object" obtained by dereferencing a null pointer, which
> causes undefined behavior."
Ok. Taget til efterretning (men det er altså stadig nyttigt ind i
mellem
-Claus
| |
Ivan Johansen (09-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 09-06-02 15:45 |
|
Claus Rasmussen wrote:
> Ok. Taget til efterretning (men det er altså stadig nyttigt ind i
> mellem
"My apprentice, beware the path to Undefined Behavior. Once you start
down that path, it will dominate your life forever. It will consume your
time, as you try to track down and fix problems."
- Herb Sutter & Jim Hyslop
Ivan Johansen
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 16:20 |
|
Ivan Johansen wrote:
> "My apprentice, beware the path to Undefined Behavior. Once you start
> down that path, it will dominate your life forever. It will consume your
> time, as you try to track down and fix problems."
Rigtigt. Men hvis nu den konsumerede tid til fejlsøgning er mindre end
den tid, der skal bruges på at lave tingene rigtigt ?
I det jeg kalder den "virkelige verden" er man nogen gange _nødt_ til at
lave noget gris, for at få tingene til at virke (og overholde deadlines).
Og så er en fed kommentar ala "// Grim hack for at få lortet til at virke"
at foretrække frem for at skulle skrive en masse kode om.
Men i teoretikernes verden forekommer den slags naturligvis aldrig, da
man under designfasen af systemet naturligvis har forudset alle problemer
så den slags slet ikke er nødvendigt
-Claus
| |
Kent Friis (09-06-2002)
| Kommentar Fra : Kent Friis |
Dato : 09-06-02 16:32 |
|
Den Sun, 09 Jun 2002 17:19:48 +0200 skrev Claus Rasmussen:
>Ivan Johansen wrote:
>
>> "My apprentice, beware the path to Undefined Behavior. Once you start
>> down that path, it will dominate your life forever. It will consume your
>> time, as you try to track down and fix problems."
>
>Rigtigt. Men hvis nu den konsumerede tid til fejlsøgning er mindre end
>den tid, der skal bruges på at lave tingene rigtigt ?
Hvor lang tid tager det at lave en "int dummy", og stikke den en
reference til den?
I forhold til at sidde og debugge et halvgammelt program, som chefen
lige har besluttet skal køre på en ny platfom, hvor det overskriver en
hel anden variabel, som først bliver brugt 800 linier længere nede i
programmet...
Mvh
Kent
--
"Handlingen blev afbrudt pga. computerens begrænsede effekt"
- Windows NT på en Pentium III 550 MHz
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 16:41 |
|
Kent Friis wrote:
> I forhold til at sidde og debugge et halvgammelt program, som chefen
> lige har besluttet skal køre på en ny platfom, hvor det overskriver en
> hel anden variabel, som først bliver brugt 800 linier længere nede i
> programmet...
Der er jo forskel på at lave en hack og at lave et møgprogram uden
kommentarer.
Jeg kan nævne et konkret eksempel på en hack:
Et mega-projekt jeg arbejdede på som programmør var i sin afsluttende
fase, da man - ups - opdagede at en bestemt sortering ikke kunne lade
sig gøre. Informationen manglede ganske enkelt i databasen, og hvis
den skulle puttes ind på en pæn måde ville det kræve en reorganisering
af af en fire-fem nøgletabeller. Og derefter rettelser i adskillige
applikationer plus naturligvis tests...
Så jeg lavede en hack - behørigt kommenteret med en advarsel om, at
denne kode absolut ikke var noget som helst portabel osv. osv.
Resultat: Projektet blev afleveret til tiden og til prisen og alle
var glade.
-Claus
| |
Jonas Meyer Rasmusse~ (09-06-2002)
| Kommentar Fra : Jonas Meyer Rasmusse~ |
Dato : 09-06-02 15:06 |
|
tak :)
"Ivan Johansen" <NG@Padowan.dk> wrote in message
news:3D035F38.3040609@Padowan.dk...
> Jonas Meyer Rasmussen wrote:
>
> > Scott Meyers skriver at resultatet af dette er 'undefined behavior', og
> > jeg antager at han har det fra C++ standarden, da jeg ikke selv har den,
kan
> > jeg desværre
> > ikke verificere det.
>
> Det står specifikt i §8.3.2.4:
> "Note: in particular, a null reference cannot exist in a welldefined
> program, because the only way to create such a reference would be to
> bind it to the "object" obtained by dereferencing a null pointer, which
> causes undefined behavior."
>
>
> Ivan Johansen
>
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 15:03 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote
> Jonas Meyer Rasmussen wrote:
>
> > -En reference referer _altid_ til et objekt.
>
> Nej.
>
Jo!!!
Så længe vi snakker om programmer med veldefineret opførsel - og hvem gider
at snakke om andet ?
> void f(int&);
>
> int main() {
> f(*(int*)0);
At dereferere en 0 pointer er undefined behaviour - uanset om det har noget
med en reference at gøre eller ej.
Processoren må gerne lave en bus-error eller general protection fault, hvis
den har lyst.
> }
>
> Den slags er af og til nyttigt.
>
At basere sig på åbenlyse hacks og undefined behaviour er aldrig nyttigt.
Venlig hilsen
Mogens Hansen
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 15:04 |
|
Mogens Hansen wrote:
> At basere sig på åbenlyse hacks og undefined behaviour er aldrig nyttigt.
Lad mig gætte: Det er ret begrænset, hvad du har lavet af programmering
i det virkelige liv
-Claus
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 15:19 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote
> Mogens Hansen wrote:
>
> > At basere sig på åbenlyse hacks og undefined behaviour er aldrig
nyttigt.
>
> Lad mig gætte: Det er ret begrænset, hvad du har lavet af programmering
> i det virkelige liv
>
Tåbelig kommentar!!!
Jeg har levet af at programmere i det virkelige liv i over 10 år!
Venlig hilsen
Mogens Hansen
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 15:25 |
|
"Mogens Hansen" <mogens_h@dk-online.dk> wrote
>
> "Claus Rasmussen" <clr@cc-consult.dk> wrote
> > Mogens Hansen wrote:
> >
> > > At basere sig på åbenlyse hacks og undefined behaviour er aldrig
> nyttigt.
> >
> > Lad mig gætte: Det er ret begrænset, hvad du har lavet af programmering
> > i det virkelige liv
> >
>
> Tåbelig kommentar!!!
> Jeg har levet af at programmere i det virkelige liv i over 10 år!
Iøvrigt adskillige gange på projekter hvor
* personers liv
* _meget_ store værdier (hundredevis af milioner kroner) og miljø
* samfund infrastruktur
har været afhængig af at programmerne virker.
Skulle det baseres bevidst på hacks og undefined behaviour i den virkelige
verden ?
Ikke med min medvirken!
Venlig hilsen
Mogens Hansen
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 15:36 |
|
Mogens Hansen wrote:
> Jeg har levet af at programmere i det virkelige liv i over 10 år!
Så du vil altså påstå, at du i løbet af de ti års programmering ikke
har lavet en eneste hack ?
Det tror jeg ikke på. Beklager
-Claus
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 15:49 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote
[snip]
>
> Det tror jeg ikke på. Beklager
>
Hvad du gætter og tror på er fuldstændigt ligegyldigt.
Viden er interessant - og du _ved_ formodentlig _intet_ om hvad jeg har
lavet professionelt de sidste 10 år!
Undlad venligst at komme usaglige, ufunderede udtalelser om det!
Venlig hilsen
Mogens Hansen
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 16:32 |
|
"Claus Rasmussen" <clr@cc-consult.dk> wrote
> Mogens Hansen wrote:
>
> > Jeg har levet af at programmere i det virkelige liv i over 10 år!
>
> Så du vil altså påstå, at du i løbet af de ti års programmering ikke
> har lavet en eneste hack ?
>
Hvor påstod jeg det ?
Hvorfor er det relevant ?
Har du overvejet at det kan være min _erfaring_ med hacks (uanset om det er
mine eller andres) at det i længden giver flere problemer end det løser, og
at det er bedre at løse problemerne ved at ændre designet i en mere ren
retning ?
Venlig hilsen
Mogens Hansen
| |
Ken (09-06-2002)
| Kommentar Fra : Ken |
Dato : 09-06-02 19:52 |
|
> Lad mig gætte: Det er ret begrænset, hvad du har lavet af programmering
> i det virkelige liv
>
> -Claus
Gæt igen!
/Ken
| |
Per Abrahamsen (14-06-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 14-06-02 14:51 |
|
Claus Rasmussen <clr@cc-consult.dk> writes:
> I det jeg kalder den "virkelige verden" er man nogen gange _nødt_ til at
> lave noget gris, for at få tingene til at virke (og overholde deadlines).
Ja, men man bør tænke på
*(int*)0
på samme måde som
#define private public
#include "otherlib.h"
#undef private
for at få adgang til private members, altså et uhyggeligt grimt hack
der kan bruges som en nødløsning, men som man _ved_ vil koste dyrt
senere fordi man har overtrådt kontrakten.
| |
Thomas Krog (09-06-2002)
| Kommentar Fra : Thomas Krog |
Dato : 09-06-02 14:08 |
|
> Er der nogen, der kan give en god forklaring på forskellen - fordele
> og/eller ulemper - mellem call by reference og call by reference with
> pointer arguments.
Item 1 fra "more effective c++" handler om netop dette ("Distinguish between
pointers and references"). Refencer er primært indført af syntax årsager så
man fx. kan have en matrix klasse hvor man for matrix objekter a,b og c kan
skrive:
a = b+c; // pga. referencer behøver b og c ikke nødvendigvis at blive
kopieret
De væsentligste 2 forskelle mellem referencer og pointerer er nok:
-at en reference _skal_ referere til et objekt hvorimod en pointer godt kan
være en null pointer.
-at en reference er tvunget til hele tiden at referere til det samme objekt,
hvorimod en pointer godt kan starte med at referere til et objekt og senere
ændres til at referere til et andet objekt.
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 16:07 |
|
Hej.
Takker for de grundige svar. Jeg fik fat i det vigtigste.
Jeg har ikke programmeret specielt længe, så det med den 'tomme
reference' venter jeg lidt med at forstå. Jeg ved, at pointere kan
være nullet - og helst altid er det, når de ikke bruges. Det må være
godt nok for mig, indtil videre.
Tak igen.
MVH
Henrik
| |
|
|