A.connected_to[0] = &B;
Czy skopiować coś: tymczasową wartość wskaźnika wyrażenia &B
.
Klasy szablonów wektorowych zawsze zajmują się automatyczną budową i zniszczeniem kopii, ale kopiowanie konstrukcji typu pierwotnego jest równoznaczne z przypisaniem i zniszczeniem typu pierwotnego, w tym wskaźników, nie jest opcją.
Wskaźnik jest bardzo podstawowym typem - prawie nic nie jest automatycznie wykonywane przy użyciu wskaźników. Pod maską to tylko integralna wartość odpowiadająca adresowi w pamięci. Kiedy usuniesz wskaźnik, kompilator po prostu ufa ci, że wskaźnik przytrzymuje adres (lub "wskazuje na") obiekt odpowiedniego typu.
Na przykład, biorąc pod uwagę klasy Foo i bar, które nie są związane przez dziedziczenie:
Foo *ptr1, *ptr2;
Bar *ptr3;
// All pointers are uninitialized.
// Dereferencing them is undefined behavior. Most likely a crash.
// The compiler will almost certainly issue a warning.
ptr1= new Foo(); // ptr1 now points to a valid Foo.
ptr2 = ptr1; // ptr2 points to the same Foo.
ptr3=(Bar*)ptr1; // This is an obvious programmer error which I am making here for demonstration.
// ptr3 points to the same block of memory as ptr1 & 2.
// Dereferencing it is likely to do strange things.
delete ptr1; // The compiler is allowed to set ptr1 to 0, but you can't rely on it.
// In either case dereferencing ptr1 is once again undefined behavior
// and the value of ptr2 is unchanged.
Kompilator jest znacznie mniej prawdopodobne, aby wydać ostrzeżenie, jeśli uzna to za ptr1
dereferencjonowane po usunięciu niż przed inicjalizacji. Praktycznie nigdy nie wyda ostrzeżenia, jeśli usuniesz obiekt ptr2
po usunięciu obiektu przez ptr1
. Jeśli nie jesteś ostrożny, tak jak ostrzegali cię inni, twój wektor wskaźników może spowodować nieumyślne wywołanie nieokreślonego zachowania w ten sposób.
I wprowadził bardzo źle odlew Foo*
do Bar*
zilustrować absolutną ufność kompilator w ciebie. Kompilator pozwala to zrobić i szczęśliwie potraktuje bity tak, jakby były pasku, gdy wyłączysz ptr3
.
Biblioteka standardowa C++ udostępnia kilka klas szablonów, które oferują zachowanie podobne do wskaźnika z dużo bardziej automatycznym bezpieczeństwem. Na przykład, std::shared_pointer
:
std::shared_ptr
jest inteligentny wskaźnik, który zarządza żywotność obiektu, zazwyczaj przydzielane z new
. Kilka obiektów shared_ptr
może zarządzać tym samym obiektem; obiekt zostanie zniszczony, gdy ostatni pozostały do niego wskaźnik zostanie zniszczony lub zresetowany. Obiekt jest zniszczony przy użyciu polecenia delete-expression lub niestandardowego deletera, który jest dostarczany do shared_ptr
podczas budowy.
Jeśli w twoim środowisku nie ma jeszcze biblioteki standardowej C++ 11, może ona dostarczyć bibliotekę boost lub przestrzeń nazw std::tr1::
. Oba zapewniają bardzo podobne shared_ptr
. std::auto_ptr
, które na pewno masz, jest podobne, ale pozwala tylko jednemu obiektowi auto_ptr
odwoływać się do obiektu w określonym czasie. (C++ 11 wprowadza std::unique_ptr
jako zamierzonego zamiennik auto_ptr
. Na auto_ptr
jest zgodne z większością std pojemników szablonu. unique_ptr
może być umieszczony w pojemniku szablonu std::move
).
Możliwe jest wkręcona z tych klasy przez utrzymywanie lub uzyskiwanie wskaźnika i małpowanie z nim, np
Foo *basic_ptr=new Foo();
std::auto_ptr<Foo> fancy_ptr(basic_ptr);
delete basic_ptr; // Oops! This statement broke our auto_ptr.
Będziesz także je łamać, jeśli przechodzą w adresie zmiennej w automatycznym przechowywania:
Foo aFoo;
std::auto_ptr<Foo> fancy_ptr(&aFoo); // automatic storage automatically breaks auto_ptr
Jeśli po prostu zrobić std::shared_ptr<sn> fresh_sn(new sn())
a następnie użyć std::vector< std::shared_ptr<sn> >
Będzie dobrze.
Wypróbowanie różnych rzeczy jest zwykle dobrym sposobem, aby dowiedzieć się, jak naprawdę działają. Potrafię obsłużyć proste i * z typami pierwotnymi i przekazywać je przez odniesienie itp. Do funkcji - ale powyższe wymaga zrozumienia, w jaki sposób struktura i wektor są zaimplementowane itp. W pewnym stopniu =) – Deniz
Aby się nauczyć Sugeruję wdrożenie minimalnych przypadków testowych różne podejścia, które rozważasz; użyj gdb lub innego debuggera, aby uruchomić te minimalne przykłady i obserwuj, jak zachowują się w szczegółach - niż możesz podjąć świadomą decyzję. –