31 Ağustos 2018 Cuma

Default Member Initialization Yani In-class Member Initializers

Giriş
C++11 ile geliyor. Açıklaması şöyle.
C++11 added member initializers, expressions to be applied to members at class scope if a constructor did not initialize the member itself.

Örnek
Şöyle yaparız.
struct Bar {
  const int b = 5; // initialization (via default member initializer)
  ...
};
Örnek
Şöyle yaparız.
class Foo {
  int x = 0;
  int y{}; // same effect.
};
Örnek
Şöyle yaparız.
struct Foo
{
  explicit Foo(int i) : i(i) {} // x is initialized to 3.1416
  int i = 42;
  double x = 3.1416;
};

27 Ağustos 2018 Pazartesi

std::ratio Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <ratio>
Constructor - Bölünen
Bölen 1 kabul edilir. Şöyle yaparız.
using Zero = ratio<0>;
using One = ratio<1>;
Constructor - Bölen + bölünen
Şöyle yaparız. 1 / 2 anlamına gelir.
std::ratio<1, 2> foo;
ratio_greater_equal
Örnek ver

ratio_divide
Örnek ver

ratio_multiply
Örnek ver

Örnek
Elimizde şöyle bir kod olsun.
/* "Strong" speed type, unit is always [m/s]. */
struct Speed {
   long double value;
};

/* "Strong" length type, parameterized by a unit as multiples of [m]. */    
template <class Period = std::ratio<1>> struct Length {
   unsigned long long value;
};
Length yapısını ilklendirmek için elimizde şöyle bir kod olsun.
#include <ratio>

auto operator ""_m(unsigned long long n)
{
   return Length<>{n};
}

auto operator ""_km(unsigned long long n)
{
   return Length<std::kilo>{n};
}
Şöyle yaparız.
/* We use auto here, because the suffix is so crystal clear: */
const auto lengthInMeter = 23_m;
const auto lengthInKilometer = 23_km;
Diğer
Bu sınıfı kendimiz yazsaydık şöyle yapardık.
class Fraction {
  int numerator{}, denominator{};
public:

  Fraction() = default;
  Fraction(int n, int d):
        numerator(n), denominator(d) {}
  ~Fraction() = default;

  void set_num(int value) { numerator = value; }
  void set_den(int value) { denominator = value; }
  int get_num() const { return numerator; }
  int get_den() const { return denominator; }

  ...

};

xvalue Nedir

Giriş
xvalue şöyle tanımlanır. Bir metoddan dönen rvalue xvalue olarak adlandırılır. Aslında rvalue ile aynı şeydir.
— An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue reference is an xvalue. —end example ]
Açıklaması şöyle.
rvalue reference returned from function is qualified as xvalue, which belongs to rvalue.






delete operator kullanımı - delete epxression

delete operator
delete operator aynı zamanda "delete expression" olarak ta bilinir. delete operator belleği işletim sistemine geri vermek zorunda değildir.

global delete operator
Açıklaması şöyle
In some cases, the operator delete might be redefined -actually overloaded- (for example, your Class might define it and also define operator new). By coding ::delete you say that you are using the standard, "predefined", deletion operator.

A typical use case for redefining both operator new and operator delete in some Class: you want to keep a hidden global set of all pointers created by your Class::operator new and deleted by your Class::operator delete. But the implementation of your  delete will remove that pointer from the global set before calling the global ::delete
Örnek
Global delete operator kullanmak için ::delete şeklinde kullanılır. Şöyle yaparız.
void DoWork(ExampleClass* ptr)
{
  ::delete ptr;
}

delete operator ve sanitization (hijyen)
delete operator silinen pointer'a yeni bir değer atar (temizlik açısından) veya atayamaz diye bir kural yok. Bunun gerekli olup olmadığı uzun yıllar boyunca tartışıldı. Belli bir uzlaşmaya varılmadı. Derleyiciler kendi kurallarını uyguluyorlar.

Örneğin Visual Studio 2015'ten itibaren delete operator'ü pointer'a 0x8123 değerini atıyor. Elimizde şöyle bir kod olsun
#include <iostream>

using namespace std;

int main()
{
    int* ptr = new int;
    cout << "ptr = " << ptr << endl;
    delete ptr;
    cout << "ptr = " << ptr << endl;

    system("pause");

    return 0;
}
Çıktı olarak şunu alırız.
ptr = 0050BC10
ptr = 00008123
double delete
double delete tanımsız davranış (undefined behavior) getirir.
Obj *op = new Obj;
Obj *op2 = op;
delete op;
delete op2; // What happens here?
delete [] ve delete işlemlerinin karıştırılması
new ile alınan bellek mutlaka delete ile silinmeli.
new[] ile alınan bellek tek boyutlu dizi olsa bile mutlaka delete [] ile silinmeli.
char * ch = new char;
delete ch; //OK

char * ch = new char;
delete[] ch; //Error

char * ch = new char[1];
delete ch; //Error !
char * ch = new char [1];
delete[] ch; //OK
iki boyutlu dizi için delete
Array şöyle yaratılır.
int** myArray = new int*[100];
for(int i = 0; i < 100; i++){
    myArray[i] = new int[3];
}
Sonra şöyle silinir.
for(int i = 0; i < 100; i++)
    delete [] myArray[i]; // delete all "rows" in every "column"

delete [] myArray; // delete all "columns"
void* için delete
void* delete edilemez. Açıklaması şöyle.
warning: cannot delete expression with pointer-to-'void' type 'void *' [-Wdelete-incomplete]
Şu kod hatalı.
void foo(void* p) {
  delete p;
}