Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Konverzija iz T*& u const T*&

[es] :: C/C++ programiranje :: Konverzija iz T*& u const T*&

Strane: 1 2 3

[ Pregleda: 8624 | Odgovora: 55 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Konverzija iz T*& u const T*&16.09.2008. u 12:28 - pre 189 meseci
Zašto C++ nema podrazumevanu konverziju iz tipa T*& u const T*&, već moram ručno da vršim konverziju? Primer:

Code:

#include <iostream>

using namespace std;

void f(const int *&x) {
    cout << *x << endl;
}

int main() {
    const int *a = new int(5);
    int *b = new int;
    
    f(a);
    *b = 3;
//    f(b);                   Greska!
    f((const int*&) b); //  OK
    
    return 0;
}

Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-35.BVCOM.NET.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&16.09.2008. u 13:09 - pre 189 meseci
Zato sto kad stavis const a imas i * i &, kompajler podrazumeva referencu na pointer na konstantni int ;)
Kako je iz konverzije T* u const T* rezultat temporary, referenca se na to ne moze
bindovati pa kompajler prikazuje gresku.

recimo ako umesto funkcije stavis ovaj template, proci ce ti bez greske
zato sto tada kompajler zna da se radi o const referenci:

Code:

template <typename T>
void f(const T& x) {
    cout << *x << endl;
    }
// sintaksu za const pointer, const referencu mozes i preko typedefa da resis.


Ovo je kako je pisac kompajlera razmisljao.
E sad kako bi trebalo da radi po standardu, i da li je to po standardu ostavljam
nekome drugom ;)

Pozzz!


[Ovu poruku je menjao Branimir Maksimovic dana 16.09.2008. u 14:22 GMT+1]
 
Odgovor na temu

yaelo
Rajko Vojnović
Beograd

Član broj: 78087
Poruke: 153
87.250.52.*



+9 Profil

icon Re: Konverzija iz T*& u const T*&16.09.2008. u 13:10 - pre 189 meseci
const int*& - to ti je referenca na tip podataka, koji je u ovom slucaju pointer na const int variablu, sto nije isto kao referenca na pointer na int variablu. Moze da se predaje int* kao parametar funkciji koja prima int const*.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&16.09.2008. u 16:16 - pre 189 meseci
Kada je parametar tipa T*&, to znači da mogu da menjam ne samo vrednost objekta na koji se pokazuje, nego i sam pokazivač na njega. Sa druge strane, kada je parametar tipa const T*&, to znači da sam objekat na koji se pokazuje funkcija ne menja, ali da sam pokazivač može. Na primer:

Code:

void obrisi(const int *&x) {
    if (x != 0) {
        delete x;
        x = 0;
    }
}

void razdvoj(int *&x, int *&y) {
    if (&x == &y) {
        throw("Razdvajanje nije moguce");
    }
    if (x == y) {
        if (y != 0) {
            y = new int;
            *y = *x;
        }
        return;
    }
    if (x == 0) {
        x = new int;
        *x = *y;
        return;
    }
    if (y == 0) {
        y = new int;
        *y = *x;
    }
}


Primeri nemaju previše praktičnog smisla, služe samo kao ilustracija. Kada definišem pomenljivu tipa T*, ona pokazuje na objekat tipa T, koji se može menjati. Ako ja imam objekat kome dozvolim menjanje, a funkcija garantuje da ga neće menjati, u čemu je problem?

Ne bih rekao da prilikom konverzije bilo kog tipa A u bilo koji tip B, pri čemu su oba reference na nešto ima bilo kakvih privremenih objekata.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-35.BVCOM.NET.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&16.09.2008. u 18:31 - pre 189 meseci
Prvo, ne postoji konverzija iz tipa reference u tip reference, zato sto su one aliasi za odredjeni tip.
Dakle kad bacis funkciji referencu na neki objekat u stvari to je isto kao da si bacio sam objekat.
Drugo, ne bacas referencu na objekat, nego sam objekat u tvom primeru, ali sa obzirom na prvo sto rekoh,
to ti dodje na isto.
Trece, rezultat svake konverzije ti je temp objekat. Naravno ne kreira kompjaler to stvarno,
osim ako nije neophodno.
No da ne duzim pricu, probaj sledece:

Code:

#include <iostream>

using namespace std;

typedef const int* T;
void f(const T& x) {
    cout << *x << endl;
    }

int main() {
  T a = new int(5);
// T& a = new int(5) , non const referenca ne moze na temp
  int* b = new int;      
  const T& c = new int(6); // const referenca moze na temp
                
  f(a); // nema konverzije
  *b = 3;
  f(b); // konverzija (int*) -> (const int*), 
  // ali temp ide na const referencu pa se kompajler ne buni
  return 0;
}


Pozdrav!
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&17.09.2008. u 09:07 - pre 189 meseci
Code:

#include <iostream>

using namespace std;

void postavi_na_nulu(const int *&x)
{
    x = 0;
}

int main()
{
    int x, *y = &x;
    postavi_na_nulu((const int*&) y); // bez konverzije je greska

    if (y==0)
        cout << "Nula" << endl;

    return 0;
}


Privremeni objekat o kome pricas moze biti referenca (to jest adresa) promenljive tipa int*, to jest, na masinskom jeziku je ekvivalentan sa int**, a ne sa int* (znam da masinski jezik ne zna za tipove). No, kao sto i sam kazes, temp moze na const&, pa zasto onda u ovom primeru ne moze bez konverzije, jer se svakako ide na const&?

Razlika izmedju mog i tvog primer je u tome sto deklaracija parametra sa int*& garantuje da se nece menjati objekat tipa int na koji pokazuje preneti pokazivac, a sam pokazivac moze da se preusmeri na drugu adrtesu, a kod tebe se garantuje da su i objekat na koji se pokazuje i sam pokazivac nepromenljivi unutar funkcije. To nije isto.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
87.250.42.35



+1064 Profil

icon Re: Konverzija iz T*& u const T*&17.09.2008. u 16:07 - pre 189 meseci
Masinski jezik zna za tipove. Privremeni objekat ne moze biti c++ referenca. No moze biti tipa int**
no kakve sad to ima veze sa ovim?
U tvom primeru ne ide na const& i bas zato imas gresku dva puta sam vec objasnio.

Code:

postavi_na_nulu((const int*&) y); // bez konverzije nije greska


ovde ne dolazi do konverzije vec jednostavno forsirano dodajes const na int* tip.
Problem je sto po defaultu dolazi do konverzije a kad kastujes u referencu na const int*, ne dolazi
do konverzije. U stvari c++ ima 4 vrste kastova, c style cast jednostavno leze na jedan od
ta cetiri, sto ce reci u zavisnosti od slucaja cast povlaci konverziju ili reinterpretaciju.

Medjutim,

Code:


postavi_na_nulu((const int*) y); // sa konverzijom je greska i ovo se desava po defaultu
// pa i da ne stavis cast operator



Mislim da tebe buni sto ne dolazi do inicijalizacije iz int* u const int*& po defaultu
nego moras da kastujes.
Pa zato sto na taj nacin mozes da modifikujes const objekte bez kastovanja

Na pr:

Code:


int main()
{
  const int a = 5;
  int *b;
//  const int*& c = b; ne moze jer to je posredno bypassovanje const korektnosti
  const int*&c = const_cast<const int*&>(b); // opasno, ali bar se vidi kao upozorenje
  c = &a; // ne valja, sada b pokazuje na const objekat
  *b = 42; // undefined behavior, bum tras
}




Jel sad jasno?

Pozdrav!

 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&19.09.2008. u 11:19 - pre 189 meseci
Mašinski jezik ne zna za tipove, ali nema veze, nije to ovde tema.

Napisao si

Code:

postavi_na_nulu((const int*&) y); // bez konverzije nije greska


Evo, kompajliram bez konverzije i dobijam grešku. Nemoj da se ljutiš, ali zamolio bih te da proveriš kod pre nego što ga okačiš. Ako ne dobiješ grešku, reci kojim kompajlerom kompajliraš kod. Ja korictim g++ (trenutno sam pod Linux-om).
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-66.bvcom.net.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&19.09.2008. u 16:51 - pre 189 meseci
Masinski jezik ima tipove, imas ono dword qword word byte i slicno. I to leze na masinske
instrukcije koje operisu sa tim tipovima. Imas signed i unsigned operacije te operacije koje
rade sa stringovima. Potom masinski ima i float double i long double tipove
Ovde mislim na masinski za x86.

Kada castujes iz (int*) -> (const int*&) tada nema konverzije. To sam napisao
i vidi se iz citata.
Jel ti to mene uopste ne razumes?
E sad da se razumemo po c++ standardu imas dve vrste konverzija.
Jedna je kada konerzija za rezultat daje rvalue a druga lvalue.
Kada kastujes u referencu tada je rezultat konverzije lvalue, a to ja ne
zovem konverzijom vec reinterpretacijom.
I sta si kompajlirao posto iz onog citata definitivno nisi mogao
bilo sta da kompajliras jer to je jedna linija iz tvog koda sa izmenom komentara?

Pozdrav!

edit: cemu ova diskusija? objasnio sam ti sto ne mozes inicijalizovati referencu
na const int* iz pointera na int i to je to.




[Ovu poruku je menjao Branimir Maksimovic dana 19.09.2008. u 18:07 GMT+1]
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&26.09.2008. u 08:42 - pre 189 meseci
Citat:
Branimir Maksimovic: I sta si kompajlirao posto iz onog citata definitivno nisi mogao
bilo sta da kompajliras jer to je jedna linija iz tvog koda sa izmenom komentara?


Kompajlirao sam onaj program koji sam priložio sa jedinom izmenom što je izbačena konverzija. To se ne kompajlira na g++/Linux kombinaciji. Ako si taj kod kompajlirao uspešno nečim drugim, onda bi mogao da napišeš i čime si ispeo da kompajliraš ovaj program:

Code:
#include <iostream>

using namespace std;

void postavi_na_nulu(const int *&x)
{
    x = 0;
}

int main()
{
    int x, *y = &x;
    postavi_na_nulu(y);

    if (y==0)
        cout << "Nula" << endl;

    return 0;
}


Mašinski jezik je jezik nula i jedinica, a ono o čemu si pričao je asembler. No, na mašinskom jeziku postoje operacije nad sadržajima datih adresa, tako da nad sadržajem na istoj adresi možeš da vršiš sve operacije. Komp te niučemu ne sprečava. Kad na C-u napišeš struct {int x,y;} t = 2.7; dobićeš poruku o grešci. Znam da i u C-u možeš tipove na silu da konvertuješ, kao i da koristiš unije, ali nekakva kontrola tipova postoji - u mešinskom jeziku ne.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-173.bvcom.net.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&26.09.2008. u 15:57 - pre 189 meseci
Jel ti mene zezas?
Izmenio sam komentar, rekoh objasnio n puta o cemu se radi? Nisam rekao da bez casta radi
odakle ti to i sto mi to inputiras. REKAO SAM DA SA CASTOM U REFERENCU NEMA KONVERZIJE i izmenio komentar
a ne da ce bez casta da kompajlira. I sto je sad to bitno ;) ?
Sa konverzijom tj kad ne castujes u referencu dolazi do greske, to sam napisao.

Sto se masinskog tice, preporucio bih ti da procitas Intel® 64 and IA-32 Architectures
Software Developer’s Manual

tu ces naci zanimljive stvari kao sto su:

CHAPTER 4
DATA TYPES
4.1 FUNDAMENTAL DATA TYPES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-1
4.1.1 Alignment of Words, Doublewords, Quadwords, and Double Quadwords . . . . . . . . . . . . 4-2
4.2 NUMERIC DATA TYPES. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3
4.2.1 Integers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4
4.2.1.1 Unsigned Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4
4.2.1.2 Signed Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4
4.2.2 Floating-Point Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
4.3 POINTER DATA TYPES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-8
4.3.1 Pointer Data Types in 64-Bit Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-8
4.4 BIT FIELD DATA TYPE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.5 STRING DATA TYPES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.6 PACKED SIMD DATA TYPES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10
4.6.1 64-Bit SIMD Packed Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-10
4.6.2 128-Bit Packed SIMD Data Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-11
4.7 BCD AND PACKED BCD INTEGERS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-12
4.8 REAL NUMBERS AND FLOATING-POINT FORMATS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-13

a kao direktni demant ovo mi se svidja jer kao da je intelov pisac hteo direktno da te demantuje
ovom recenicom ;)

8.2 X87 FPU DATA TYPES
The x87 FPU recognizes and operates on the following seven data types (see Figures
8-13): single-precision floating point, double-precision floating point, double
extended-precision floating point, signed word integer, signed doubleword integer,
signed quadword integer, and packed BCD decimal integers.

Ovde se opsirno govori o tipovima podataka koje podrzavaju *intelovi procesori*.
Asembler je isto sto i masinski, tj obicno 1 asembler mnemonik mapira na 1 masinsku instrukciju.
Naravno makro asembler kombinuje vise instrukcija u jednu a imas i hla, Randy Hide-ov
asembler koji sa sintaksom imitira vise jezike.
No kakve sad veze ima asembler sa ovim o cemu pricamo ;)
Asembler i ne moze da radi sa tipovima podataka koje cpu ne podrzava inace bi bio visi jezik ;)

Pozdrav!

edit: naravno procesor ne radi type checking ili si i to ocekivao ;)
ali to nema veze sa tvojom izjavom da masinski ne zna za tipove podataka ;)

edit2: u stvari masinski je slican dinamicki tipovanim jezicima gde se u slucaju da dodje do
greske baca exception u run time-u radje nego u compile time-u kod staticki tipovanih jezika

[Ovu poruku je menjao Branimir Maksimovic dana 26.09.2008. u 17:34 GMT+1]

[Ovu poruku je menjao Branimir Maksimovic dana 26.09.2008. u 20:16 GMT+1]
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Konverzija iz T*& u const T*&28.09.2008. u 17:40 - pre 189 meseci
Nedeljko, biće ti najlakše, kao što ti reče Branimir, da (za početak) typedef-uješ, pa da raščlaniš jedno po jedno...
Pazi sledeću stvar, možda će biti jasnije:

Code:

#include <iostream>
using namespace std;

int main()
{
  int x = 5;

  int *a = &x; // pokazivač na int
  const int *b = &x; // nekonstantni pokazivač na konstantni int
  const int * const c = &x; /* konstantni pokazivač na konstantni int (ne možeš da menjaš ni
                                     [b]vrednost[/b] pokazivača) */
}



U tvom primeru iz prve poruke, argument funkcije f je: nekonstantna referenca na (const int*)
Međutim, sa f(b) desila se konverzija (int*)->(const int*), dobio si r-vrednost i potrebna ti je konstantna referenca.

Dakle, bez typedef-ova, deklaracija f-je f bi trebalo da bude

void f(const int * const &x);

Sve je ovo manje-više Branimir pomenuo.

Inače, ne znam koju verziju g++-a koristiš, ali bi trebalo bi da počevši od v4.3 imaš rvalue reference.

Pozdrav.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-173.bvcom.net.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&28.09.2008. u 21:06 - pre 189 meseci
Gorane hvala na podrsci, medjutim nemoj Nedeljka da mislidujes sa rvalue referencama ;)


Da pocnem, razlog zbog cega je zabranjeno bindovanje referenca na rvalue, odnosno temporary objekte
je ustvari ovakav kod:

Code:

    void f(int& a) {a++;}
     
    void g()
    {
        double b = 1;
        f(b);
    }



Stvar je u tome da su prvi c++ kompajleri ovo dozvoljavali.
Rezultat je bilo gomila bagova jer niko nije kapirao da se desava konverzija koja za rezultat
ima tmp, i ono sto se menja je tmp objekat a ne sam parametar. To je Bjarne objasnio
u svojoj knjizi Design and Evolution of C++.
Medjutim danas se pojavila potreba za tako necim jer u slucaju da referenca nije output
parametar, vec ukoliko postoji potreba da se petlja sa tmp objektom u samoj funkciji,
(ono sto zovu "move semantics") onda je sasvim legalno imati referencu na rvalue.

I to je glavni razlog sto se uvela nova sintaksa u jezik?

E sad to u gcc-u jel nesto eksperimentalno ili su vec teorijski zaokruzili i izbacili
novu verziju jezika, odnosno standarda za jezik?

Pozdrav!

 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Konverzija iz T*& u const T*&28.09.2008. u 23:07 - pre 189 meseci
Ono što treba Nedeljku je već napisano.

----

Da, generalno se javila potreba za novom sintaksom da bi postojala podrška (move semantika) i za primitivne tipove, dok je kod korisnički definisanih tipova moguće svaki put implementirati Move konstruktor, ali je i to poprilično dosadno (eleganto, kratko, ali dosadno :))

Neke stvari iz novog standarda su implementirane (u GCC-u recimo postoje rvalue reference), ali ih ljudi ne koriste previše zato što neke njima ortogonalne još uvek nisu implementirane...

Što se tiče povratnih vrednosti...

Code:

const T& f()
{
  T obj;
  return(obj); //ups!!!
}


Code:

T f()
{
  T obj;
  return(obj); //ovo je ok
}


Code:

...
T x = f(); //ok, x možemo da menjamo, ali smo jedanput više bespotrebno kopirali objekat (*)
const T &y = f(); //jednom manje kopiran objekat, ali je read-only
T &&z = f(); //rvalue referenca :)
...


(*) Teorijski, to jeste tako, praktično nije, zato što se vrši NRVO optimizacija.

U principu, pojava rvalue referenci je najviše možda posledica potrebe za perfect forwarding-om, ali kako nisu svi kompajleri implementirali variadic templejte, to i ne postoji za sada preterana potreba za njima.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-173.BVCOM.NET.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&28.09.2008. u 23:58 - pre 189 meseci
Imam samo dve primedbe.

Prvo zadnji vazeci standard je revizija onog iz 98. tj ovaj iz 2003.

Ono sto ce se zvati c++0x ce biti uradjeno sledece godine i zvace se valjda c++09.
Za sada je to na nivou predloga koji ce mozda biti prihvaceni a mozda i nece.

Drugo,

Code:

T f()
{
  T obj;
  return(obj); //ovo je ok
}
.....
const T &y = f(); //jednom manje kopiran objekat, ali je read-only
.....


ovo je ok zato sto postoji specijalno pravilo da temp bindovan na const referencu zivi dok
zivi sama referenca inace zivi do kraja izraza ili funkcije.
medjutim,
Code:

T &&z = f(); //rvalue referenca :)


za ovaj slucaj nisam siguran. u predlogu za prosirenje jezika sa rvalue referencama (koji sam video ),
nigde ne stoji zahtev da se jezik izmeni u tom smislu. U stvari vec vidim gomilu problema
sa zivotom tmp objekata bindovanih na rvalue reference.
No o tome cemo sledece godine kad izadje bar draft verzija papira ;)


Pozdrav!
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 00:58 - pre 189 meseci
Slažem se, ali recimo, diskusije radi, zašto bi bilo šta bilo loše što se tiče života tmp objekta? Pojasni, na šta misliš?
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-173.BVCOM.NET.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 02:15 - pre 189 meseci
Mislim na gomilu slucaja koji ce morati da se pokriju ukoliko bude potrebno vezivati
zivot tmp objekta za zivot rvalue reference. Hocu da kazem,
da ce recimo T&& f(T&& p){ return p; } biti veoma cest bug zbog analogije sa T& f(T& p){return p;}.
Drugo kako ce tu sta da se rezolvuje pojma nemam ;) no imamo g++ 4.3 pa se moze videti.
Trece, sam predlog uopste ne razmatra zivot tmp-a u odnosu na rvalue referencu,
no opet ko proba kako je implementirano sa gcc -om moze videti sta tu moze da se ocekuje.
Mislim da bi se ozbiljno diskutovalo o ovome potrebno je dosta vremena ;)

Pozdrav!



 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 02:26 - pre 189 meseci
Da, ono što si napomenuo može biti bug, ali šta ćeš, ljudi će se navići da ne greše. Razlika u sintaksi je jasnija.

Što se života tmp objekta tiče, čini mi se da je on uvek lokalan (zapravo, skoro 100% sam siguran, napisaću primer ako bude trebalo...sada je malo kasno...), tako da treba da živi u scope-u u kom je kreiran, a da se posle toga briše. To je to.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 13:38 - pre 189 meseci
Javiću se još jednom, čisto da bih objasnio da nikoga nisam zezao. Ako neko smatra da ga zezam, ne mora da se nervira i odgovara ili može da mi napiše da sam budala, ne ljutim se, nema veze. U nastavku ovog posta ću pisati o tome šta me je zanimalo, a u sledećem postu kakve sam odgovore dobio i kako sam reagovao (čisto da bi oni koji ne žele da čitaju jedno od to dvoje mogli lakše da preskoče onaj deo koji ih ne zanima).

Inače, sav kod koji ovde okačim je testiran g++ kompajlerom (gcc version 4.2.2) pod Linux sistemom. Ako se nekome rezultati ne poklope sa onim što napišem (u smislu komnpajliranja / nekompajliranja i / ili pucanja / nepucanja i / ili drugačijih rezultata) molim da napiše čime kompajlira kod. Ako neko bude želeo da odgovara, molim da testira kod koji kači, a bilo bi lepo i da napiše čime kompajlira.

Jano je meni da neke stvari ne mogu da radim, jer me kompajler grdi. Ja svoje prktične probleme uspešno rešavam i vrlo dobro znam šta su lvrednosti, šta dvrednosti i šta su privremeni objekti.

Međutim, ono što je mene zanimalo je zašto kreatori jezika / pisci kompajlera nisu razmišljali na sledeći način: da postoji automatska konverzija iz int*& u const int*&, tako što se adresa pokazivačke promenljive baca na stek, jer konceptualno (sa stanovišta projektovanja jezika) ne bi trebalo da bude problema.

Ja se ne bih bunio da int objekat koji šaljem Peri po referenci (u stvari, šaljem pokazivač na int po referenci) bude promenjen, ali mi Pera obeća da ga neće menjati (onaj int na koji se pokazuje), ja mu kažem, sve i da ga promeni, meni to nije problem itd. Zbog čega je meni opasno da Peri dam takvu pošiljku? Sa stanovišta implementacije, samo se šible adresa pokazivača na stek i gotovo.

Kod nepokazivačkih tipova ovo baš tako i radi. Sledeći program radi ispravno

Code:
#include <iostream>

using namespace std;

void ispisi(const int &x)
{
    cout << x << endl;
}

int main()
{
    int a = 5;
    ispisi(a);
    
    return 0;
}


Kod pokazivačkih tipova situacija nije ista, jer const int* znači da se int na koji se pokazuje neće menjati, a da sam pokazivač može dobiti neku drugu vrednost (recimo, 0 ili da bude preusmeren na neki drugi int). No, iz sličnih razloga ne vidim smisao uvođenja zabrane zbog koje sledeći program ne može da se kompajlira

Code:
#include <iostream>

using namespace std;

void ispisi(const int *&x)
{
    if (x==0)
    cout << "NULL" << endl;
    else
        cout << *x << endl;
}

int main()
{
    int *a = new int(5);
    ispisi(a);
    
    return 0;
}

p.cpp: In function ‘int main()’:
p.cpp:16: error: invalid initialization of reference of type ‘const int*&’ from expression of type ‘int*’
p.cpp:5: error: in passing argument 1 of ‘void ispisi(const int*&)’


Sa druge strane, sledeći program radi

Code:
#include <iostream>

using namespace std;

void ispisi(const int *&x)
{
    if (x==0)
    cout << "NULL" << endl;
    else
        cout << *x << endl;
}

int main()
{
    int *a = new int(5);
    ispisi((const int*&) a);
    
    return 0;
}


No, posle je Branimir napisao za liniju koda koji proizvodi grešku (na mom kompajleru) da ne proizvodi grešku. Naravno, to je bila linija koda iz programa koji sam okačio, pa se podrazumevao taj kontekst.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.dynamic.sbb.rs.



+2789 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 13:44 - pre 189 meseci
Citat:
Branimir Maksimovic: No da ne duzim pricu, probaj sledece:

Code:

#include <iostream>

using namespace std;

typedef const int* T;
void f(const T& x) {
    cout << *x << endl;
    }

int main() {
  T a = new int(5);
// T& a = new int(5) , non const referenca ne moze na temp
  int* b = new int;      
  const T& c = new int(6); // const referenca moze na temp
                
  f(a); // nema konverzije
  *b = 3;
  f(b); // konverzija (int*) -> (const int*), 
  // ali temp ide na const referencu pa se kompajler ne buni
  return 0;
}



E, ad. Na to sam odgovorio sa

Citat:
Nedeljko: Razlika izmedju mog i tvog primer je u tome sto deklaracija parametra sa int*& garantuje da se nece menjati objekat tipa int na koji pokazuje preneti pokazivac, a sam pokazivac moze da se preusmeri na drugu adrtesu, a kod tebe se garantuje da su i objekat na koji se pokazuje i sam pokazivac nepromenljivi unutar funkcije.


Sad vidim da sam se zeznuo. U oba slučaja je zabranjeno menjati objekat, a pokazivač se može preusmeravati. Branimirov primer je bio dobar, ali nije bio ono što je mene zanimalo.

Potom je Branimir okačio tačan i ilustrativan kod.

Code:
int main()
{
  const int a = 5;
  int *b;
//  const int*& c = b; ne moze jer to je posredno bypassovanje const korektnosti
  const int*&c = const_cast<const int*&>(b); // opasno, ali bar se vidi kao upozorenje
  c = &a; // ne valja, sada b pokazuje na const objekat
  *b = 42; // undefined behavior, bum tras
}


Priznajem da ga nisam pročitao, jer prethodni komentar (da se kompajlira nešto što se ne kompajlira) nije bio tačan. No, ipak ne smatram da sam ikoga zezao.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

[es] :: C/C++ programiranje :: Konverzija iz T*& u const T*&

Strane: 1 2 3

[ Pregleda: 8624 | Odgovora: 55 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.