30 Nisan 2015 Perşembe

C++ Notlarım POD

Default Initialization Nedir?
Default Initialization yazısına taşıdım.

Zero Initialization Nedir?(C++98)
Bir değişkene 0 değerinin atanmasıdır.

Value Initialization Nedir? (C++03)
Value Initialization yazısına taşıdım.

POD Nedir?
POD C gibi yazılan, constructor, destructor, virtual metod gibi C++'a mahsus hiçbir şey içermeyen struct veya sınıflara verilen isimdir. Member method POD olmasına engel değildir.

POD Örnekleri
1. Static member POD olmasına engel değildir.
struct POD
{
  int x;
  char y;
  void f() {} //no harm if there's a function
  static std::vector<char> v; //static members do not matter
};
2. Destructor POD olmasına engeldir.
struct AggregateButNotPOD1
{
  int x;
  ~AggregateButNotPOD1(){} //user-defined destructor
};
3. non-POD member variable POD olmasına engeldir
struct AggregateButNotPOD2
{
  AggregateButNotPOD1 arrOfNonPod[3]; //array of non-POD class
};
4. Farklı access modifier kullanılması POD olmasına engeldir.
struct B {
public:
    int m1;
private:
    int m2;
};

C++ Kodlarında POD'un Yeri Nedir?
POD tanım olarak sadece veridir. Nesneye yönelik programlamanın temeli veri artı davranış üzerine oturtulmuştur. Bu yüzden C++ programlarımda pod en çok state taşımak için kullanılır. Örneğin socket üzerinden veri göndermek veya Java'daki serializable nesneleri gibi bir yere yazılıp okunma işleri için uygundurlar.

memcpy ve POD
Veri taşırken bazen veriyi memcpy ile sockete, shared memory alanına yazmak gerekir. POD tipler memcpy ile kullanılabilir. Örnek:

#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
memcpy(buf, &obj, N); // between these two calls to memcpy,
// obj might be modified
memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
// holds its original value

Konuyla ilgili olarak Data Alignment başlıklı yazıya göz atabilirsiniz.


POD Kontrolü
Bir tipin POD olup olmadığını is_pod kullanarak aşağıdaki gibi öğrenebiliriz.
#include <type_traits
std::is_pod <T>::value;

C++11 ile POD
Eski C++ standardındaki POD kavramı biraz katıydı. C++11 ile POD kavramı 2 alt kavrama daha ayrıldı. Bunlar trivial class ve standart layout class. Standart layout diğer dillerle iletişim için var.

Trivial class aynı zamanda trivally copyable kavramınıda içerir. Yani superset'idir.

Yeni kavramlar için yeni metodlar da eklendi.

template <typename T>
struct std::is_pod;
template <typename T>
struct std::is_trivial;
template <typename T>
struct std::is_trivially_copyable;
template <typename T>
struct std::is_standard_layout;
Trivial Class
Artık memcpy ile bir sınıfı kullanmak için trivial class olması yeterli. POD'a göre gevşetilen kurallar şöyle.
1. Artık tüm member'lar aynı access modifier seviyesinde olmak zorunda değil.
struct Trivial4 {
public:
    int a;
private: // no restrictions on access modifiers
    int b;
};
2. Static değişkenler non-Trivial olabilir.
struct Trivial8 {
     int x;
     static NonTrivial1 y; // no restrictions on static members
}
3. Default constructor olması yeterli.
struct Trivial9 {
     Trivial9() = default; // not user-provided
      // a regular constructor is okay because we still have default ctor
     Trivial9(int x) : x(x) {};
     int x;
}
Standart Layout
Bu konuyu sonra yazacağım.

POD Initialization
Default Initialization
Default initialization ile POD içindeki field'lar rastgele değerler ile doldurulur. Örnek:

MyPodClass instance2;//Fields are garbage
MyPodClass* instance3 = new MyPodClass;//Fields are garbage

POD ve Zero Initialization
POD'ların 0 ile doldurulması için aşağıdaki örneğe dikkat etmek gerekir.

//Struct does not have a constructor
struct X {
 int field;
}
X x; //Default initialized. Not zero initialized
X x = {}; // Zero initialized
X x = X(); // Zero initialized
X* x = new X () // Zero initialized

Pod Dizisi ve Zero Initialization
POD'lardan oluşan bir diziyi 0 ile doldurmak için memset kullanılabilir.
 
struct X {};
X myArray [10]; //array'deki elemanlar default initialize edilir
memset (myArray,0,sizeof(myArray)); //array'deki elemanlar 0 ile doldurulur

Bir başka yöntemde ise struct'a default constructor ekleniyor. Ama bu sefer yapı POD olmuyor. Sadece örnek olsun diye ekledim.
struct X {
  Test (){}//Zero Initialize all members
private:
  X (const X&);
  X& operator=(const X&);
          }

Non-POD ve Initialization

Primitive Dizi ve Zero Initialization
Primitive diziler aşağıdaki gibi zero initialize edilebilir.
int array[100] = {};
Döngü ile 0 atamak veya memset yapmak arasındaki hız farkını bilmek mümkün olmayabilir.

Non-POD Value Initialization
Örnekte non-pod yapının primitive alanları value initialization ile ilklendirilir.

struct Struct {
    Struct() : memberVariable() {}
    int memberVariable;
};

Java ve Default Initialization
Java bir sınıf içindeki field'ları constructor çağırılmadan önce default değerleri ile ilklendirir.

C# ve Default Initialization
C# bir sınıf içindeki field'ları constructor çağırılmadan önce default değerleri ile ilklendirir. Default değerin ne olduğu burada yazıyor. C++'takinin aksine default değerler garbage değiller. Scalar tipler için default değer 0'dır.
  • For a variable of a value-type, the default value is the same as the value computed by the value-type's default constructor (Section 4.1.1).
  • For a variable of a reference-type, the default value is null.



Hiç yorum yok:

Yorum Gönder