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: 8751 | 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.



+2790 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 13:53 - pre 190 meseci
Poenta mog pitanja je bila (ne mora niko da odgovori ako neće, nemam nameru nikoga da nerviram):

Zašto se lepo ne prati semantika: const int *p je pokazivač na konstantan objekat u smislu da se neće objekat moći menjati preko pokazivača p (možda će jga menjati neko drugi) i slično za reference na pokazivače? Druga je stvar kada esencijalno imamo konverziju (binarni sadržaji nisu isti, kao kod int i float) ili je drugi pokazivač na tabelu virtuelnih metoda i slično, pa privremeni objekat mora da se pravi, pa ne može referenca na privremeni objekat itd.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
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 13:54 - pre 190 meseci
Ma nije da si nekog zezao, nego, ne znam da li si video ono što sam ti ja posle toga napisao...

Postoji razlika između sledeće dve stvari:

Code:

void ispisi(const int * const &x);
...
...
...
ispisi(a);


i

Code:

void ispisi(const int *&x);
...
...
...
ispisi((const int*&) a);


Sve će ti biti jasno ako razlikuješ ove dve stvari...
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

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



+2790 Profil

icon Re: Konverzija iz T*& u const T*&29.09.2008. u 14:12 - pre 190 meseci
Ma, znam sve to. To se valjda vidi i iz mojih postova da razlikujem const int *p i int * const q.

Code:
int main() {
    const int *p = new int(22);
    // *p = 77; error: assignment of read-only location
    delete p;
    p = 0;
    int const *q = new int(5); // primer koji se sustinski ne razlikuje od prethodnog
    // *q = 77; error: assignment of read-only location
    delete q;
    q = 0;
    int * const r(new int(7));
    *r = 77;
    // r = 0; error: assignment of read-only variable r
    return 0;
}


No, ovde je došlo do nesporazuma oko toga šta ja zapravo pitam.
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*&29.09.2008. u 14:52 - pre 190 meseci
Tvoje pitanje je jasno mada ne postoji konverzija iz reference u referencu, medjutim

Code:

int a;
float b;
const int& ra = a;
const int& rb = b; // da, mozes i ovo


je analogno

Code:

int* a=0;
int* const &cra = a;


a ne

Code:

int* b=0;
//const int* &rcb = b;


jer ovde imas non const referencu na const int*, a u prvom slucaju imas const referencu na int* ,
mislim da je u tome glavna stvar nesporazuma.

Dakle kada napises ovo drugo,dolazi do konverzije int* u const int* i stvaranja tmp objekta.

Pozdrav!
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
89.216.145.*



+2790 Profil

icon Re: Konverzija iz T*& u const T*&30.09.2008. u 08:19 - pre 190 meseci
Citat:
Branimir Maksimovic: Tvoje pitanje je jasno mada ne postoji konverzija iz reference u referencu


E to je ono sto me je zanimalo. Zasto projektanti jezika nisu odlucili da omoguce konverziju reference u referencu, kada je tip isti, do na const manipulator, gde non-const ide na const? Sta bi bilo lose u takvom C++ -u? U tom slucaju nema esencijalne potrebe za privremenim objektom, a nema ni int& -> float& perverzija. No, nema veze necu vise da smaram.
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*&30.09.2008. u 10:47 - pre 190 meseci
Mislim da pogresno zamisljas reference. To nisu pointeri nego aliasi. Ne mozes imati referencu na referencu,
pointer na referencu ili cak ni niz referenci, jer one same za sebe ne zahtevaju bilo kakav storage.

To sto implementacija moze i uglavnom koristi pointere da implementira reference nema veze sa njihovom semantikom.
Uvedene su u jezik da bi mogla da se ostvari sintaksa izraza u kojima objekti funkcionisu bas kao
i osnovni tipovi.

E sad sto se tice konverzija i tmp objekata, to je sve proisteklo iz toga da bi se takodje omogucila
elegantna sintaksa izraza i overloadovanje operatora itd itd. Na kraju krajeva kada napises
neki izraz tu ima potencijalno gomila medju-rezultata.

Sa referencama ne treba razmisljati u smislu konverzije nego vezivanja objekta za alias
jer referenca semanticki nije varijabla i ne nosi vrednost kao recimo pointeri
pa je ne mozes ni konvertovati u nesto.

Drugo, da si pitao, sto ne mogu da implicitno konvertujem int** u const int**, tu bi odgovor bio
jasan, jer ovo je zabranjeno zbog const korektnosti (naveo sam i to za svaki slucaj)
zato sto su pointeri varijable koje imaju vrednost,
a u ovom slucaju vrednost bi bila rezultat konverzije.
Medjutim takve zabrane kod referenci nema jer se reference uvek binduju za nesto, a ako
dodje do konverzije binduju se za rezultat konverzije sto je tmp, pa onda i ne mozes menjati
preko reference vrednost originalnog objekta nego njegove konvertovane kopije.

Ne znam kako da ti objasnim bolje ;)
U c++, standardna konverzija se definise kao formiranje tmp objekta t iz izraza e : T t(e);
Dakle zamisli da je referenca nesto sto ne postoji nego je samo sintaksna zamena za neku
varijablu ili konstantu, dakle rezultat konverzije se ne smesta kao vrednost u referencu
nego se referenca binduje(vezuje na nasem?) za taj rezultat.
Za svaki kast ce naci da ako se nesto kastuje u referencu rezultat konverzije je lvalue,
a u suprotnom dolazi do standardne konverzije lvalue to rvalue, array to pointer, function to pointer.
E sad zasto ne mozes non const referencu bindovati za tmp objekat.
Pa zato sto mnogi generalno gledano smatraju da bi svi tmp objekti trebali biti
konstante. No sa novitetom koji dolazi sledece godine, Goran je to napomenuo,
kao sto su rvalue reference, stvar se menja. Neki rvalue objekti su
konstante a neki nisu te ima smisla menjati vrednost tmp objekata u slucaju nekih optimizacija.

Pozdrav!
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
89.216.145.*



+2790 Profil

icon Re: Konverzija iz T*& u const T*&30.09.2008. u 12:10 - pre 190 meseci
Citat:
Branimir Maksimovic: Drugo, da si pitao, sto ne mogu da implicitno konvertujem int** u const int**, tu bi odgovor bio
jasan, jer ovo je zabranjeno zbog const korektnosti (naveo sam i to za svaki slucaj) zato sto su pointeri varijable koje imaju vrednost, a u ovom slucaju vrednost bi bila rezultat konverzije.


Upravo je to suština mog pitanja. int** je pokazivač na pokazivač na int, a const int** je pokazivač na pokazivač na konstantan int. Jasno je meni da obrnuta konverzija (const int** -> int**) ne sme da se dozvoli, jer bi to bilo narušavanje const korektnosti, ali ne vidim kako bi konverzija int** -> const int** naručila const korektnost. Takođe, sa stanovišta implentacije jezika, u tom slučaju nije neophodno stvarati privremeni objekat. E, sad, ako su se dogovorili da svaka konverzija rezultuje privremenim objektom (a jesu), opet ne vidim smisao tog pravila. Postoje konverzije kod kojih je pravljenje privremenog objekta neophodno i one gde to nije neophodno.

Zašto se ne može referenca vezati za privremeni objekat, jasno je.

Code:

int* f(int& x) {
    return &x;
}
...
int x = 2, y = 3, *p = f(x+y);


Na šta pokazuje p posle ovoga? Na bum tras prethodno oslobodjen prostor i to naravno nema nikakvog smisla.
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.173



+1064 Profil

icon Re: Konverzija iz T*& u const T*&30.09.2008. u 13:38 - pre 190 meseci
Sto se tice int** -> const int**, vec sam ti odgovorio u primeru sa referencom.

Ista stvar, nakon konverzije pokazivacu na int* posredno mozes dodeliti vrednost da pokazuje
na const int i samim tim narusavas const korektnost.

Primer iz standarda:

Citat:

[Note: if a program could assign a pointer of type T** to a pointer of type const T** (that is, if line //1
below was allowed), a program could inadvertently modify a const object (as it is done on line //2). For
example,
int main() {
const char c = ’c’;
char* pc;
//1: not allowed
const char** pcc = &pc;
*pcc = &c;
//2: modifies a const object
*pc = ’C’;
}
—end note]


Pozdrav!

 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
89.216.145.*



+2790 Profil

icon Re: Konverzija iz T*& u const T*&30.09.2008. u 15:11 - pre 190 meseci
U tom li čuču zeci grm, što ja mogu da promenim vrednost const char c i da mu zayebem const. Sad mi je kristalno jasno! Hvala veliko.

Napisao sam odgovarajući primer za reference na pokazivače

Code:

#include <iostream>

using namespace std;

int main() {
    const char c = 'A';
    char *pc;
    const char* &pcr = (const char*&)(pc);
    pcr = &c;
    *pc = 'B';
    
    if (&c==pc)
        cout << "Addresses of c and *pc are equal.\n";
    else
        cout << "Addresses of c and *pc are different.\n";
    
    cout << "c            : " << c << endl;
    cout << "*pc          : " << *pc << endl;
    cout << "*((char*)&c) : " << *((char*)&c) << endl;
    
    return 0;
}

Output:

c            : A
*pc          : B
*((char*)&c) : B


Dakle, cout << c; ipak stampa slovo 'A', čak i kada program prevodim bez optimizacije (g++ -O0 p.cpp).
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Goran Arandjelovic
Beograd

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



+9 Profil

icon Re: Konverzija iz T*& u const T*&30.09.2008. u 16:25 - pre 190 meseci
Da, napomenuo sam da će se koristiti rvalue reference, pogotovu kada je u pitanju TMP ili optimizacija nekih STL algoritama. Naime, nađi negde na Netu implementaciju vector klase (i nekih algoritama nad njim) pomoću rvalue referenci...videćeš već u kom kontekstu se javljaju tamo. Dogodila su se značajna ubrzanja jer više ne moraš da kopiraš tmp objekat prvo u neki lvalue objekat pa da tek onda operišeš nad njim.

Inače, što se tiče prethodne priče, Branimir je lepo objasnio da su to samo aliasi i ništa više i još jedna semantička razlika postoji između referenci i pokazivača (posledica tretiranja referenci kao aliasa):

Code:

const int x = 10;
const int y = 77;

const int *px = &x;

cout << *px << endl; // rezultat: 10
px = &y; // ovo je dozvoljeno, naravno...
cout << *px << endl; // rezultalt: 77



const int &rx = x;
/* E sada, ovde je referenca rx (u nekom smislu) implicitno postala konstantna nakon
inicijalizacije, tj, ovo je ekvivalentno kao da si za px rekao: const int * const px = &x */



// rx = y; 
/* Zato ovo sada i nema smisla kao što je imalo smisla za px, jer je ovde rx
(semantički) isto što i x (tj. alias), a x je const int! */




E da, a i jedan od razloga što si gore opet dobio rezultat 'A' je to što je ta konstanta u data segmentu (read-only delu data segmenta)
 
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*&30.09.2008. u 18:09 - pre 190 meseci
Samo da prokomentarisem za ono sto je rezultat dobio 'A' sa neposrednim a 'B' sa posrednim pristupom.

Prosta stvar, u C++-u konstante ne moraju da imaju rezervisano mesto u memoriji.
Kad je Nedeljko uzeo adresu konstante onda je kompajler rezervisao mesto u memoriji
i odatle cita kad ide preko pointera. Kad ide neposredno onda kompajler jednostavno
'upokuje' konstantu i uopste ne gleda sta je u memoriji.

Naravno mogao je i da zastiti var za write, onda bi dobio segfault prilikom pokusaja upisa.

Kad je ub sve je dozvoljeno.

Pozdrav!

edit:
izgleda da ce i rvalue reference imati pravilo kao i const reference sto se tice zivota tmp objekata.

ovo sam nasao ovde http://www.artima.com/cppsource/rvalue.html

a primer je :

Citat:

An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue.

A& a_ref3 = A(); // Error!
A&& a_ref4 = A(); // Ok


by Howard E. Hinnant, Bjarne Stroustrup, and Bronek Kozicki

Dakle, samo je pitanje vremena kad ce da zaokruze kako ce sve to izgeldati u standardu.
Inace Howard je lik koji je dao proposal i koji je pomogao u g++ 4.3 implementaciji .



[Ovu poruku je menjao Branimir Maksimovic dana 30.09.2008. u 19:36 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*&30.09.2008. u 19:43 - pre 190 meseci
Mislio sam upravo na tu... "upokovanu" konstantu, ona jeste u data segmentu. Ona je literal.
 
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*&30.09.2008. u 20:13 - pre 190 meseci
Pa vidi mozda je malo besmisleno ovo oko cega raspravljamo, ali da je ona upakovana u read only data segmentu
onda write sigurno ne bi prosao kao sto je slucaj kod const char* literala.
A opet da kompiler dva puta pravi storage jednom u read only a onda u read/write
segmentu za jednu konstantu to je opet gubitak prostora.
U stvari mislim da constante nemaju linkage osim ako nisu deklarisane/definisane sa extern?

Pozdrav!

edit: mislim na osnovne tipove kao konstante, naravno nesto komplikovanije zahteva
storage.

edit2: proverio sam, kad konstanta ima static ili global scope compiler je smesta u read only
data segment i onda dolazi do segfault-a prilikom upisa.
edit3: sto je i logicno jer kad je konstanta auto kompajler je verovatno smesta u stek frame
koji je r/w

[Ovu poruku je menjao Branimir Maksimovic dana 01.10.2008. u 09:38 GMT+1]

[Ovu poruku je menjao Branimir Maksimovic dana 01.10.2008. u 10:09 GMT+1]
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
89.216.145.*



+2790 Profil

icon Re: Konverzija iz T*& u const T*&01.10.2008. u 08:32 - pre 190 meseci
Ja sam onaj primer testirao sa sledecim kompajlerima:

1. GNU g++ 4.2.2 za Linux (ukljucijuci i prevodjenje sa -O0),
2. MinGW 5.1.13,
3. Borland C++ 5.5. freecommandlinetools,
4. Visual C++ 9.0

i svi su dali isti rezultat. Ja sam to shvatio da konstanta ima i svoju kopiju ciju adresu daje, a da je adresa same konstante nedostupna. No, izjasnjava li se standard o ovome?

Drugo, ja sam na ovoj temi prvi put video &&, a da to nije binarni operator (logicka konjunkcija). Sta je to? Dosta mi je i link. Ne morate da se zamarate kucanjem.
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.39.51



+1064 Profil

icon Re: Konverzija iz T*& u const T*&01.10.2008. u 08:46 - pre 190 meseci
Nema kopiju nego kompajler jednostavno radi isto kao kad opalis #define A 4 recimo,
kad pristupas neposredno, a posredno naravno mora da napravi var u memoriji.

Drugo, to sa && je nova sintaksa za rvalue reference.
Verujem da ces tada moci da kompajliras nesto ovako:

Code:

void f(const int* &&a)
{
  a=0;
}

int main()
{
  int *b = new int(5);
  f(b); // b nece promeniti vrednost posto ce rvalue biti menjana
}


No nemam g++ 4.3 da proverim teroriju ;)

Link imas u jednom od prethodnih postova da vidis o cemu se radi.

Pozdrav!
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
89.216.145.*



+2790 Profil

icon Re: Konverzija iz T*& u const T*&01.10.2008. u 10:41 - pre 190 meseci
Čak i kada napises int a = 5;, kompajler mora tu peticu da ima negde, bilo da je ona sastavni deo mašinske instrukcije, bilo da je dovlači sa neke adrese. Peticu će lako da ugradi direktno u kod. Međutim, šta ako je tip preglomazan da bi stao u mašinsku instrukciju kao parametar? Kada sam na početku prethodnog programa stavio typedef char T[10], svuda tip char zamenio sa T i konstanti c dodelio vrednost "A", na izlazu sam dobio tri puta slovo B.

Code:

#include <iostream>

using namespace std;

int main() {
    typedef char T[10];
    char x[10];
    const T c = "A";
    T *pc;
    const T* &pcr = (const T*&)(pc);
    pcr = &c;
    **pc = 'B';
    
    if (&c==pc)
    cout << "Addresses of c and *pc are equal.\n";
    else
    cout << "Addresses of c and *pc are different.\n";
    
    cout << "c            : " << c << endl;
    cout << "*pc          : " << *pc << endl;
    cout << "*((char*)&c) : " << *((char*)&c) << endl;
    
    return 0;
}

Output :

Addresses of c and *pc are equal.
c            : B
*pc          : B
*((char*)&c) : B


Da li su ove zavrzlame sastavni deo standarda ili je to do implementacije kompajlera? Indikativno je da su reyultati isti na rayli;itim kompajlerima.
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-51.BVCOM.NET.



+1064 Profil

icon Re: Konverzija iz T*& u const T*&01.10.2008. u 11:17 - pre 190 meseci
Naravno, niz od 10 karaktera nece moci da pokuje po kodu ;) pa to uvek vuce sa steka
koji je r/w.

Medjutim, probaj ovo pa vidi koji ces rezultat dobiti.

Code:

#include <iostream>

using namespace std;

    typedef char T[10];
    const T c = "A";

int main() {
    char x[10];
    T *pc;
    const T* &pcr = (const T*&)(pc);
    pcr = &c;
    **pc = 'B';

    if (&c==pc)
    cout << "Addresses of c and *pc are equal.\n";
    else
    cout << "Addresses of c and *pc are different.\n";

    cout << "c            : " << c << endl;
    cout << "*pc          : " << *pc << endl;
    cout << "*((char*)&c) : " << *((char*)&c) << endl;

    return 0;
}



edit: po standradu modifikovanje konstanti je ub pa kompajler moze da radi sta mu je volja, tj
ne moze se predvideti tacno ponasanje u svim slucajevima

Pozdrav!
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

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



+2790 Profil

icon Re: Konverzija iz T*& u const T*&02.10.2008. u 08:55 - pre 190 meseci
OK, kad su toliko zabrinuti za stvari koje se smatraju sitnicama (da li ce nesto sto se inace moze lepo isprogramirati i bez toga, moze jos malkice optimizovati), jesu li se setili da ubace i neki tip podataka za novcane iznose?
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

itf
Zagreb

Član broj: 59794
Poruke: 993
161.53.237.*



+9 Profil

icon Re: Konverzija iz T*& u const T*&02.10.2008. u 09:05 - pre 190 meseci
Citat:
Nedeljko: OK, kad su toliko zabrinuti za stvari koje se smatraju sitnicama (da li ce nesto sto se inace moze lepo isprogramirati i bez toga, moze jos malkice optimizovati), jesu li se setili da ubace i neki tip podataka za novcane iznose?


Oprosti, ali čemu fantaziranje? Novčani iznosi su potpuno opisivi realnim brojevima definiranim u C(++)u.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

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



+2790 Profil

icon Re: Konverzija iz T*& u const T*&02.10.2008. u 13:22 - pre 190 meseci
Nisu jer postoji round off error.

http://www.elitesecurity.org/t303962-0-Novi-excel-bug

Od 6 odbi 30 puta po 0.2 i neces dobiti nulu.

Za novcane iznose je bolje koristiti cele brojeve, ili jos bolje posebno dizajniranu klasu zasnovanu na celobrojnoj aritmetici. Nisu BCD brojevi i tipovi za novcan iznose (koji postoje u mnogim jezicima i drugim sw proizvodima) izmisljeni bez potrebe.
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: 8751 | Odgovora: 55 ] > FB > Twit

Postavi temu Odgovori

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