Różnice między wybraną wersją a wersją aktualną.
— |
value_initialized [2009/04/30 00:02] (aktualna) rwilk utworzono |
||
---|---|---|---|
Linia 1: | Linia 1: | ||
+ | ====== Boost::value_initialized<T> ====== | ||
+ | **Rafał Wilk** | ||
+ | ===== Wstęp ===== | ||
+ | |||
+ | Boost::value_initialized<T> zapewnia generyczny sposób inicjacji deklarowanych zmiennych, klas, wskaźników i innych typów. Korzystanie z value_initialized zapewnia zinicjowanie zdeklarowanego typu wartością domyślną w momencie deklaracji. | ||
+ | |||
+ | ===== Funkcjonalność ===== | ||
+ | |||
+ | Zadeklarować zmienną można na wiele różnych sposobów, ale nie zawsze wartość zadeklarowanej zmiennej jest oczywista. | ||
+ | |||
+ | Przykładowo: | ||
+ | |||
+ | <code> | ||
+ | T zmienna; | ||
+ | </code> | ||
+ | |||
+ | Powyższa deklaracja nie determinuje wartości zadeklarowanej zmiennej,(często w zależności od systemu operacyjnego) zmienna ta może zostać zainicjowana wartością domyślną lub też pozostawiona z wartością bliżej nie określoną. | ||
+ | |||
+ | Można próbować na inne sposoby: | ||
+ | |||
+ | <code> | ||
+ | T zmienna = 0; | ||
+ | T klasa = T(); | ||
+ | </code> | ||
+ | |||
+ | W tym wypadku pierwszy przykład poprawnie zainicjuje zmienną lecz nie poradzi sobie z inicjacją klasy. Drugi przykład nie może być stosowany dla klas, które dziedziczą po boost::noncopyable lub mają prywatny lub niezdefiniowany konstruktor kopiujący. | ||
+ | |||
+ | W tych wszystkich przypadkach swoje zastosowanie znajduje value_initialized: | ||
+ | |||
+ | <code> | ||
+ | value_initialized<T> zmienna; | ||
+ | </code> | ||
+ | |||
+ | Zapewnia inicjację wartością domyślną, 0 dla zmiennych artymetycznych, null'em dla wskaźników, wartością false dla typu bool, wykorzystuje domyślny konstruktor klasy itd.. | ||
+ | |||
+ | ===== Klasa value_initialized<T> ===== | ||
+ | |||
+ | Oto jak wygląda klasa value_initialized: | ||
+ | |||
+ | <code> | ||
+ | template<class T> | ||
+ | class value_initialized | ||
+ | { | ||
+ | public : | ||
+ | value_initialized() : x() {} | ||
+ | operator T&() const { return x ; } | ||
+ | T& data() const { return x ; } | ||
+ | |||
+ | private : | ||
+ | unspecified x ; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Udostepnia ona dwie możliwości dostępu do referencji do przechowywanego obiektu: operator T&() oraz metodę T& data(). | ||
+ | |||
+ | Dodatkowo zdefiniowane została funkcja T& get( value_initialized<T> &x ), która także pozwala na dostęp do referencji obiektu. | ||
+ | |||
+ | <code> | ||
+ | template<class T> | ||
+ | T const& get ( value_initialized<T> const& x ) | ||
+ | { | ||
+ | return x.data() ; | ||
+ | } | ||
+ | |||
+ | template<class T> | ||
+ | T& get ( value_initialized<T>& x ) | ||
+ | { | ||
+ | return x.data() ; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Co daje łącznie trzy możliwości otzrymania referencji do obiektu i wykorzystania jej: | ||
+ | |||
+ | <code> | ||
+ | void fun(&T); | ||
+ | value_initialized<T> zmienna; | ||
+ | |||
+ | fun(zmienna); | ||
+ | fun(zmienna.data()); | ||
+ | fun(get(zmienna)); | ||
+ | </code> | ||
+ | |||
+ | Ze względu na dwie wersje funkcji get, dla wartości zmiennych i const, zaleca się właśnie ten sposób dostępu do referencji. Zapewniona zostaje kontrola dostępu i dlatego też: | ||
+ | |||
+ | <code> | ||
+ | value_initialized<int> zmienna ; | ||
+ | get(zmienna) = 1 ; // poprawne | ||
+ | |||
+ | value_initialized<int const> const_zmienna ; | ||
+ | get(const_zmienna) = 1 ; // błąd: obiekt typu const | ||
+ | |||
+ | value_initialized<int> const zmienna_const ; | ||
+ | get(zmienna_const) = 1 ; // błąd: obiekt typu const | ||
+ | |||
+ | value_initialized<int const> const const_zmienna_const ; | ||
+ | get(const_zmienna_const) = 1 ; // błąd: obiekt typu const | ||
+ | </code> | ||
+ | |||
+ | ===== Przydatne zastosowania ===== | ||
+ | |||
+ | value_initialized znajdzie wiele możliwości by ułatwić życie programiście, nie jest natomiast narzędziem, bez k†órego nie można żyć. | ||
+ | |||
+ | Przydatnym może okazać się inicjacja w miejscu deklaracji: | ||
+ | |||
+ | 1. klas dziedziczących po boost::noncopyable lub z prywatnym konstruktorem kopiującym, | ||
+ | |||
+ | 2. zmiennych arytmetycznych wartością zero, | ||
+ | |||
+ | 3. wskaźników wartością null, | ||
+ | |||
+ | 4. i pewnie wiele innych w zależności od potrzeb. | ||
+ |