25 Aralık 2019 Çarşamba

Brace Initialization - Object İçin Copy List Initialization ve Direct List Initialization

Giriş
İki çeşit list initialization var. Her ikisi de constructor'ları tetikler.

1. Copy List Initialization
Object'in ismini vermeden sadece parametrelerini veriyoruz. Foo foo  = {...} şeklinde kullanılır. Bu aslında normal Copy Initialization ile aynı şey gibi ancak davranış olarak daha tutarlı. Açıklaması şöyle.
Probably, the behaviour of the new copy-list-initialization was defined to be "good" and consistent, but the "weird" behaviour of old copy-initialization couldn't be changed because of backward compatibility.
Özellikle STL veri yapıları ile çalışmayı kolaylaştırıyor.

Bu kullanımda explicit olmayan herhangi bir constructor tetiklenir.

Örnek - parametresiz
Parametresiz çağrılırsa default constructor tetiklenir.
S s = {};     // the default constructor is invoked
Örnek - parametresiz
Elimizde şöyle bir kod olsun.
std::vector<std::map<std::string, std::set<std::string>>> table;
Eskiden şöyle yapardık
table.push_back(std::map<std::string, std::set<std::string>>());
Şimdi şöyle yapıyoruz. std::map sınıfının default constructor tetiklenir.
table.push_back({});
Örnek - parametreli
Şöyle yaparız. std::initializer_list<int> alan constructor tetiklenir.
std::vector<int> v = {1,2,3};
Örnek - parametreli
Şöyle yaparız. Constructor tetiklenir.
#include <iostream>
struct Data{
   Data(int){
   }
}
int main(){
  Data d = {0};  //#1
}
Örnek - parametreli
Şöyle yaparız. Constructor tetiklenir.
struct Object {
  Object(int i) : i{i}
  {
  }

  int i;
};

Object f() { return {1}; }
Örnek - explicit constructor
Açıklaması şöyle.
In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.
Eğer sınıfın constructor metodu explicit ise derleme hatası alırız.
tuple<int, int> t2={1, 2}; // compile error
Bu durumda en azından sınıfı kurmak gerekir. Aşağıdaki örnekte direkt return 1 yazmak yerine T nesnesi ismen kuruluyor.
T func()
{
  return T{1};
}
Bu durum C++14 ile değişecek diye anlıyorum. Yani şu kod derlenecek
tuple<int, int> t2={1, 2}; 
Örnek - explicit constructor
Şöyle yaparız.
class B {};
struct A 
{
  explicit A(B const&) {}
};


int main()
{
  B b;
  A a1{b};    // compiles
  A a2 = {b}; // doesn't compile because ctor is explicit
}
2. Direct List Initialization
Object'in constructor'ını çağırır gibi parametrelerini veriyoruz. Foo foo {...} şeklinde kullanılır.

Bu aslında Direct Initialization ile aynı şey gibi. Çünkü Direct Initialization'da Foo foo (...) şeklinde kullanım var. Yine Direct Initialization'da olduğu gibi girdi gerekirse çevrime uğrayabilir.

Bu kullanımda explicit olan ve olmayan herhangi bir constructor tetiklenir.


Örnek
Şöyle yaparız. Constructor'ı çağırır.
struct foo
{
    explicit foo(int);
};

foo f {42};    // OK
Örnek
Şöyle yaparız.
sample s { new oops };
Örnek
Şöyle yaparız.
std::vector<int> v {1,2,3};
Örnek
Elimizde şöyle bir kod olsun.
template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }
};
Şöyle yaparız. Birinci kullanımda çevrim yoktur. Ancak ikinci kullanımda const char* önce std::string'e çevrilir.
Class<std::string> a{ std::string("abc") };  // works
Class<std::string> b{ "abc" };               // also works

Hiç yorum yok:

Yorum Gönder