static local variable etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
static local variable etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

8 Haziran 2017 Perşembe

Static Global ve Local Değişken

static kelimesi
static kelimesi overloaded bir kelime. Değişkenler veya metodlar için kullanılabilir.
Global değişken, lokal değişken, member değişken, global metod, member metod için kullanılabilir.
static global değişken
Açıklaması şöyle
3.6.2 Initialization of non-local variables
...
Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.
Static global değişken program çalışmaya başlamadan yani main metoduna girmeden daha önce yaratılır.
Örnek - char * 
Main metodu çalıştıktan sonra ilklendirmek için şöyle yaparız.
static const char *my_static_string = nullptr;

...

void load_static_string()
{
  if(!my_static_string)
  {
    std::string str = //Read string from file.
    my_static_string = new char[str.size() + 1];
    strncpy(my_static_string, str.data(), str.size() + 1);
  }
}
Örnek - std::vector
Şöyle yaparız.
#include <vector>

std::vector<int> v;

int main()
{
    v.push_back(1);
}
Static Order Initialization Fiasco
Static Order Initialization Fiasco yazısına taşıdım.

static local değişken metod ilk kez çağırıldığında yaratılır
static local değişken yazısına taşıdım.

virtual static değişkenler
Genellikle her sınıfa yeni bir ID vermek için kullanılır. İki tane yöntem gördüm.

1. Her sınıf için static local değişken
İlk yöntem de her sınıfın static local bir ID değişkeni vardır. Bu değişken nesnenin ilk getXXX metodu çağrıldığında ata sınıfın yine static olan sayacı +1 yapılarak atanır. Sınıfların hangi değeri alacağı kontrol edilemez.

Önce bir ata sınıf tanımlanır. Ata sınıfın pure virtual bir metodu ve bir de sayaç görevi gören bir metodu vardır.
class Base {
   public:

      virtual int getCompType() = 0;

   protected:

      static int getNextCompType()
      {
         static int nextType = 0;
         return ++nextType;
      }
 };
Her kalıtan sınıf şöyle bir yöntem izler
class Real1: public Base {
   public:
  static int getCompTypeImpl()
  {
     static int myType = Base::getNextCompType();
     return myType;
  }

  int getCompType() override
  {
     return getCompTypeImpl();
  }
};
2. Her sınıf için static member değişken
Bu yöntemde her sınıfın static bir member değişkeni vardır. Bu değişken global bir sayaçtan yeni değer alır. Sınıfların hangi değeri alacağı kontrol edilemez.

class MyInterface{
virtual int getID() = 0;
};

class MyClass : public MyInterface{
COMPONENT(); //Arayüzü gerçekleştiren macro

SET_ID(MyClass); //cpp dosyasındaki sayaçtan yeni değeri alan macro

#define  COMPONENT()\
static int ID;\//Statik değişken tanımla
int getID(){return ID};//Arayüzü gerçekleştir

#define SET_ID(Component)\
int Component::ID = GetNextID();//GetNextID sayaçtan gelen yeni sayı


19 Ocak 2016 Salı

Static Yerel (Local) Değişken

static local değişken metod ilk kez çağırıldığında ilklendirilir - non-trivial initialization
C++'ta bir nesnenin storage duration ve lifetime süreleri farklı şeylerdir. static local değişken için storage alanı uygulama ilk defa başlatılırken ayrılır.

Ancak ilklendirme yani lifetime'ın başlaması değişebilir. Eğer değişken trivial bir tipse tipse, hem storage hem lifetime uygulama açılırken başlatılabilir. Şöyle bir metodumuz olsun
{static int i = 0;}
i değişkenine 0 değeri en başta atanabilir. Metodun ilk kez çağrılmasını beklemeye gerek yoktur.

Eğer static local değişken constructor'a  sahip bir nesne ise, ilklendirme işlemi metod ilk kez çağrıldığında yapılır.Şöyle bir metodumuz olsun
void func1()
{
  static X i;
  ...
}
Bu metod ilk kez çağrıldığı zaman, X nesnesinin constructor metodu çağrılır.

static local değişken guard ile korunur
X nesnesi multi-threaded kod tarfından kullanılıyorsa, yaratılmasında problem olabilir. Bu yüzden derleyici bizim için X değişkeninden önce guard koyar.
void func1()
{
  static X i;
  static guard x_is_initialized;
    if ( __cxa_guard_acquire(x_is_initialized) ) {
        X::X();
        x_is_initialized = true;
        __cxa_guard_release(x_is_initialized);
    }
  ...
}
Gömülü bir platformda bir kez
Undefined reference to __cxa_guard_acquire
Undefined reference to __cxa_guard_release
hatasını bu yüzden almıştım.

static local değişken'in özyinelemeli kod kullanılması
Secure Coding için şöyle bir paragrah var.
Do not reenter a function during the initialization of a static variable declaration. If a function is reentered during the constant initialization of a static object inside that function, the behavior of the program is undefined. Infinite recursion is not required to trigger undefined behavior, the function need only recur once as part of the initialization.
Bu şu anlama geliyor. Static değişken kendini ilklendirmek için özyinelemeli kod kullanmamalı.
int foo(int i) {
  static int s = foo(2*i); // recursive call - undefined
  return i+1;
}
Böyle bir kod şu exception'a sebep olur.
terminate called after throwing an instance of '__gnu_cxx::recursive_init_error'
  what():  std::exception
static local değişken ve heap
Static local değişkeni heap'te yaratabiliriz.

class B {
  public:
   static const B* GetInstance() {
     static B* b = new B ();
     return b;
   }
};
Ancak uygulama sonlanırken önce static local değişken yok olacağı için heap'teki nesneyi silme şansımız olmayacaktır. Bu gibi durumlarda std::unique_ptr kullanmak iyi bir fikir.

class B {
  public:
   static const B* GetInstance() {
     static std::unique_ptr<B> b( new B() );
     return b.get();
   }
};

static local değişkenin yok edilmesi
static local değişkenlere program kapanırken dokunmamak gerekir.
If a function contains a block-scope object of static or thread storage duration that has been destroyed and the function is called during the destruction of an object with static or thread storage duration, the program has undefined behavior if the flow of control passes through the definition of the previously destroyed block-scope object.

Aşağıdaki kod tanımsız iş yapar.
void theFunction()
{
  static std::unique_ptr<int> foo { new int(42) };
}

struct Creator
{
  Creator() { theFunction(); }
};


struct Destroyer
{
  ~Destroyer() { theFunction(); }
};

Destroyer d;
Creator c;

int main()
{}