Thread overview
C++ explicit and implicit conversion
May 20, 2018
hsencan
May 20, 2018
fatih (fatih)
May 21, 2018
hsencan
May 20, 2018

Merhaba,
C++ ta 2 farklı conversion işlemi yapıldığını gördüm. Hatalı değilsem bu işlemlerine "type punning" deniyor. Peki explicit ile implicit conversion arasındaki farklar nedir ? Ve hangisini nerede tercih etmeliyim ?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 20, 2018

Implicit conversion'lar, derleyicinin kullanicidan bisey beklemeden otomatik olarak gerceklestirdigi donusumlere deniyor:

int x = 5;
float x = y;

const char* str = "hello"
std::string a = a;

struct foo
{
   foo(const char* x);
};

struct goo
{
   operator const char*(); // imlicit olarak const char*'a donusebiliyor
};

void hi(const char*);

goo g{};
hi(g); // implicit olarak const char* olusturuluyor

void bar(foo f);

bar("hello"); // foo otomatik construct ediliyor

Performans endiselerinden dolayi implicit donusumlerden genellikle cok hoslanmayiz. Ornegin en sondaki 'bar("hello")' cagrisi hic caktirmadan bir foo olusturuyor. Istedigimiz sey, kullanici bu tarz bir donusum istiyorsa, acik sekilde (explicit olarak) yazmasi: 'bar(foo{"hello"});'. Bu noktada kullanici aradaki gecici 'foo' nesnesinin farkinda ve belki daha verimli bir sekilde ayni isi yapabilir.

C++'da donusum islemleri (operator T() ve tek arguman alan constructor'lar) varsayilan olarak implicit calisiyor, yani kullanici gecici nesneyi explicit olarak olusturmak zorunda degil. Bunu zorunlu hale getirmek icin bahsedilen fonksyonlari 'explicit' olarak isaretleyebiliyoruz:

struct foo
{
   explicit foo(const char*);
};
struct goo
{
   explicit operator const char*();
};


goo g{};
hi(g); // derlenmeyecek
hi(static_cast<const char*>(g)); // tamamdir, explicit olarak donusum istedik

bar("hello"); // derlenmeyecek
bar(foo("hello")); // tamamdir, explicit olarak constructor cagrisi yaptik

Tavsiye olarak, aksi icin ozel bir sebep yoksa butun tek argumanli constructor ve donusum operatorleri explicit isaretlenmeli.

Type punning bunlardan farkli bir konu. Yukardakiler donusumu yaparken yeni bir nesne cikariyor, yani elinizde 'const char*' varsa, bundan yeni bir 'std::string' nesnesi olusturuyorsunuz ve bu tamamen guvenli bir operasyon.

Type punning durumunda, var olan bir nesneyi baska bir tipmiscesine kullaniriz. Temel olarak da 'reinterpret_cast' ve 'union'lar araciligiyla yapilir:

union fi
{
   float f;
   int i;
};

fi a;
a.f = 3.5f;
std::cout << a.i << '\n'; // a.f olsa sorun yok

Type punning yaptiginiz zaman genellikle elde ettiginiz objeyi kullanmaniz undefined behaviour'a yol acar. Ornegin yukardaki 'a.i' kismi aslinda C++ standardina gore anlamsiz bir ifade.

Type punning'den, eger low level biseyler yazmiyorsak kesinlikle kacinmamiz gerekir.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 21, 2018

Teşekkürler.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]