Default Initialization Nedir?
Bir değişkene değer ileride yazılacağı farz edilerek, değer atanmadan yaratılması anlamına
gelir. Yani default initialization sonrasında değişkenin değeri belirsizdir.
Tamamen hızlı çalışmaya yönelik bir karardır. C++'ta hata yapılmasına çok müsait bir ortam oluşturmaktır. Bu yüzden Java gibi dillerde gerek yerel değişkenler (local variable) gerekse sınıfı değişkenleri (member variable) kesinlikle default initiliazation ile ilklendirilmezler!
Açıklaması şöyle.
Default initializaiton kullanan basit bir örnek şöyle.
Derleyiciler "Path Analysis" yapıp yapmamak konusunda serbesttirler. İlklendirilmemiş değişkenler konusunda uyarı vermeyebilir Örnek'te iki tane ilklendirilmemiş değişken var ve derleyici uyarı vermiyor.
1. Stack'teki POD için Default InitializationBir değişkene değer ileride yazılacağı farz edilerek, değer atanmadan yaratılması anlamına
gelir. Yani default initialization sonrasında değişkenin değeri belirsizdir.
Tamamen hızlı çalışmaya yönelik bir karardır. C++'ta hata yapılmasına çok müsait bir ortam oluşturmaktır. Bu yüzden Java gibi dillerde gerek yerel değişkenler (local variable) gerekse sınıfı değişkenleri (member variable) kesinlikle default initiliazation ile ilklendirilmezler!
Açıklaması şöyle.
Use of an uninitialized variable: This is commonly known as source of problems in C programs and there are many tools to catch these: from compiler warnings to static and dynamic analyzers. This improves performance by not requiring that all variables be zero initialized when they come into scope (as Java does). For most scalar variables, this would cause little overhead, but stack arrays and malloc'd memory would incur a memset of the storage, which could be quite costly, particularly since the storage is usually completely overwritten.Örnek - Yerel Değişken
Default initializaiton kullanan basit bir örnek şöyle.
int i; //uninitialized
std::cin >> i;//read initial value
Örnek - Yerel DeğişkenDerleyiciler "Path Analysis" yapıp yapmamak konusunda serbesttirler. İlklendirilmemiş değişkenler konusunda uyarı vermeyebilir Örnek'te iki tane ilklendirilmemiş değişken var ve derleyici uyarı vermiyor.
void Test ()
{
int var1 ; // not initialized at this point
int var2 ; // not initialized at this point
if (2 < var2)
{
...
}
}
Default initialization kuralları şöyle.- Eğer değişken bir array ise yine aynı şekilde garbage değer taşır.İngilizcesi şöyle.
- Eğer değişken bir sınıf ise ve default constructor'ı varsa çağırılır (bu durumda non-pod olur)
- Eğer sınıfın default constructor'ı yoksa derleyici bir tane yaratır ve onu çağırır.
To default-initialize an object of type T means:(7.1) — If T is a (possibly cv-qualified) class type (Clause 12), constructors are considered. The applicable constructors are enumerated (16.3.1.3), and the best one for the initializer () is chosen through overload resolution (16.3). The constructor thus selected is called, with an empty argument list, to initialize the object.(7.2) — If T is an array type, each element is default-initialized.(7.3) — Otherwise, no initialization is performed.
Alanlar ilklendirilmez.
Örnek
Elimizde şöyle bir POD olsun
class C {
int x;
};
Bu sınıfa derleyici constructor üretir ama x değerini ilklendirmez.C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage
ÖrnekElimizde şöyle bir kod olsun
struct event_counts {
std::uint64_t counts[MAX_COUNTERS];
event_counts() = default;
};
Açıklaması şöyle.Then default initialization
event_counts counts;
will leave counts.counts uninitialized (default initialization is a no-op here), and value initialization
event_counts counts{};
will value initialize counts.counts, effectively filling it with zeros.
2. Stack'teki non-POD için Default Initialization
Elle yazılan default constructor tüm alanlara değer atamazsa, alanlar default initialize edilir. Yani ilklendirilmez
MyNonPodClass instance1;//members will not be initialized
Örnek - Çok Bariz Undefined Behavior
Elimizde şöyle bir kod olsun. Bu kodda Foo yapısının x alanına bir değer atanıyor. Daha sonra Foo
placement new ile ilklendiriliyor ve tüm belleği memset ile sıfırlanıyor
struct Foo {
int x = 0;
Foo() {}
};
// slightly simpler bar()
int bar(void* buf) {
std::memset(buf, 0, sizeof(Foo));
Foo* foo = new(buf) Foo;
return foo->x;
}
Üretilen assembly kodu şöyle
bar(void*):
mov DWORD PTR [rdi], 0 <----- memset(buff, 0, 4) or int x = 0?
They are redundant, so it's only done once.
xor eax, eax <----- Set the return value to 0
ret
Bu kodu şu hale getirelim
struct Foo {
int x;
Foo() {}
};
// ... same bar
Üretilen assembly kodu şöyle. Burada x alanına memset olmasına rağmen değer atanmadığı görülebilir.
bar(void*):
mov eax, DWORD PTR [rdi] <----- Just dereference buf as the result ?!?
ret
new'den sonra () yapılırsa alanlar zero initalize edilir.
MyPodClass* instance3 = new MyPodClass;//members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//members are zero initialized
4. Global Değişkenler
Zero initialize edilir. Şöyle yaparız.
int i; //zero-initialized
struct A{
int i;
};
struct B
{
B(){};
B(int i) :i{i}{}
int i;
int j;
};
A a; //a.i is zero-initialized
int main()
{
int j; //not initialized
int k{}; //zero-initialized
A b; //b.i not initialized
int* p = new int; //*p not initialized
A* q = new A; //q->i not initialized
B ab; //ab.i and ab.j not initialized
B ab2{1}; //ab.j not initialized
int xx[10]; //xx's element not initialized.
int l = i; //OK l==0;
int m = j; //undefined behavior (because j is not initialized)
int n = b.i; //undefined behavior
int o = *p; //undefined behavior
int w = q->i; //undefined behavior
int ex = x[0] //undefined behavior
}
Hiç yorum yok:
Yorum Gönder