Zaawansowane programowanie w C++ (PCP)
Wykład 7 - sprytne wskaźniki.
dr inż. Robert Nowak
20 kwietnia 2007
Potrzeba współdzielenia kodu źródłowego
Pojęcia niezależne od typu:
I kolekcje (np. listy)
I algorytmy (np. znajdowania największego elementu)
Szablony
I mechanizm czasu kompilacji
I kod nie jest kompilowany, jeżeli nie został użyty
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Problem typu
Typowy problem - jawne wskazanie, że identyfikator jest typem
class Foo { public:
typedef int Element;
/* dalsza część implementacji klasy Foo */
};
template<typename T> void f(const T& t) {
//Poniżej błędnie zakłada, że T::Element to nazwa składowej T::Element e = 0;
//...
//Poniżej jawnie wskazano, że T::Element to nazwa typu typename T::Element e = 0;
//...
};
boost::scoped_ptr
I Odpowiada strategii „zdobywanie zasobów jest inicjowaniem”
I Destruktor usuwa wskaźnik
I Zabronione kopiowanie
template<typename T> class scoped_ptr : noncopyable { public:
explicit scoped_ptr(T* p = 0) : p_(p) {}
˜scoped_ptr(){ delete p_; } //Usuwa obiekt wskazywany T& operator*() { return *p_; }
T* operator->() { return p_; } private:
T* p_; //Wskaźnik, którym zarządza };
void f() {
scoped_ptr<MojaKlasa> klasa(new MojaKlasa);
//kod, który może wyrzucać wyjątki
} //Destruktor klasy scoped_ptr wywoła operator delete
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Wzorzec „pimpl” - ukrywanie implementacji
class Foo { public:
//Interfejs klasy private:
//Implementacja jest ukryta
struct Impl;//Deklaracja poprzedzająca scoped_ptr<Impl> pImpl_;//Sprytny wskaźnik };
I zalety
I wady
std::auto_ptr - kopiowanie jest przekazywaniem własności
I Odpowiada strategii „zdobywanie zasobów jest inicjowaniem”
I Destruktor usuwa wskaźnik
I Dozwolone kopiowanie (!) - przenosi ono uprawnienia
template<typename T> class auto_ptr { public:
explicit auto_ptr(T* p = 0) : p_(p) {}
//nie jest const auto_ptr& !
auto_ptr(auto_ptr& a) p_(a.p_) { a.p_ = 0L; }
auto_ptr& operator=(auto_ptr& a); //nie jest const auto_ptr&
˜auto_ptr() { delete p_; } //usuwa obiekt wskazywany T& operator*() { return *p_; }
T* operator->() const { return p_; } private:
T* p_;
};
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
std::auto_ptr - przykłady
#include <memory>
using namespace std;
class Foo { /* implementacja */ };
//funkcja zwraca wskaźnik na obiekt
auto_ptr<Foo> createFoo(int n) { return auto_ptr<Foo>(new Foo(n) ); } {
auto_ptr<Foo> p(new Foo(1) );
/* tutaj wykorzystuje obiekt klasy */
}//automatycznie wolany destruktor
createFoo(2); //nie wykorzystana wartość zwracana zostanie usunięta {
auto_ptr<Foo> v = createFoo(3);
/* wykorzystanie obiektu v */
}//destruktor zwalnia zasob
std::auto_ptr niebezpieczeństwa
#include <memory>
using namespace std;
class Foo { /* implementacja */ };
//Niebezpieczne! użycie auto_ptr jako argumentu void read(auto_ptr<Foo> p) { /* wykorzystuje */ } {
auto_ptr<Foo> x = createFoo(4);
read(x);
//teraz x nie wskazuje na nic!
}
//Niebezpieczne! użycie auto_ptr w kolekcji vector<auto_ptr<Foo> > v;
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
boost::shared_ptr - sprytny wskaźnik
counter
object shared_ptr
I konstruktor : tworzy licznik i inicjuje go na 1
I konstruktor kopiujący: zwiększa licznik odniesień
I destruktor: zmniejsza licznik odniesień, jeżeli ma on wartość 0 to kasuje obiekt
sprytny wskaźnik - przykład
#include <boost/shared_ptr.hpp>
using namespace boost;
class Foo { /* implementacja */ };
{
shared_ptr<Foo> p1(new Foo(1) );
{
shared_ptr<Foo> p2(p1);
//licznik odniesien == 2 /* ... */
} //destruktor p2, licznik = 1 } //destruktor p1 usuwa obiekt
counter
object p1 1
counter
object p1 2
p2
counter
object p1 1
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
sprytny wskaźnik - przykład 2
#include <boost/shared_ptr.hpp>
using namespace boost;
class Foo { /* implementacja */ };
//funkcja zwraca wskaźnik na obiekt shared_ptr<Foo> createFoo(int n) {
return shared_ptr<Foo>(new Foo(n) );
}
{
shared_ptr<Foo> p2 = createFoo(2);
}//destruktor zwalnia zasob
counter
object p1 1
counter
object p1 2
p2
counter
object
1
p2
Sprytny wskaźnik boost::shared_ptr
I zalety
I wady
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Sprytne wskaźniki - podsumowanie
I std::auto_ptr
I boost::shared_ptr
I boost::weak_ptr
I boost::intrusive_ptr
Model wodospadowy
Wodospadowy („tradycyjny”) model tworzenia oprogramowania:
1. analiza, 2. projektowanie, 3. implementacja, 4. testowanie, 5. wdrożenie,
6. pielęgnacja. Czas
Koszt
Wady:
I duże ryzyko niepowodzenia projektu,
I długi czas sprzężenia zwrotnego.
Przyczyny:
I wykładniczy (względem czasu) wzrost kosztów zmian w projekcie.
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Extreme programming
Możliwości uzyskania innej krzywej kosztu zmian w czasie:
I prostota projektu,
I automatyczne testy,
I nastawienie na ciągłe zmiany w projekcie,
I polepszenie komunikacji.
Czas Koszt
Właściwości:
I krótki czas sprzężenia zwrotnego,
I mniejsze ryzyko niepowodzenia projektu.
Zmniejszenie ryzyka niepowodzenia projektu
I dobrze sprecyzowany cel projektu,
I krótkie wersje,
I planowanie krótkofalowe,
I ciągła weryfikacja założeń.
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Zmniejszenie kosztów zmian
I Utrzymywanie działającej wersji przez cały czas:
I automatyczne testowanie:
I modułów,
I funkcjonalne.
I ciągła integracja.
I Utrzymywanie kodów źródłowych dobrej jakości
I zmiana struktury programu bez zmiany funkcjonalności (refactoring)
I przegląd kodu.
I Poprawa komunikacji:
I kolektywne prawo do zmian kodu,
I stosowanie narzędzi zarządzających wersjami.
Sterowanie projektem
I koszt,
I czas,
I jakość,
I zakres.
dr inż. Robert Nowak Zaawansowane programowanie w C++ (PCP)
Podsumowanie
Zasady XP:
I krótkie cykle oprogramowania,
I nieustanne testowanie,
I natychmiastowa integracja,
I brak szczegółowego projektu,
I brak szczegółowego planu.