Wskaźnik a realokacja.

0

Ciekawi mnie pewna zagwozdka. Załóżmy taką sytuację:

Jest sobie std::vector, przechowuje on elementy klasy Sth (std::vector<Sth> vec). Następnie ustawiam sobie wskaźnik na wybrany element std::vectora (Sth * ptr = vec[3];). Wybrany element ma jakiś adres w pamięci (0x111111), zatem taka wartość będzie przypisana do zmiennej ptr. Używam sobie tego wskaźnika a w std::vectorze przybywa to coraz nowszych elementów, aż nagle, brakuje miejsca i std::vector realokuje swoje zasoby. W tym momencie ja dalej używam ptr, który wskazuje na obszar zwolnionej do ponownego zagospodarowania pamięci. I nagle robi się problem?

Mam dużą liczbę ciężkich obiektów upchniętych na wektorze, dlatego między klasami przesyłam jedynie wskaźnik na dany element. W pewnym momencie, część klas korzysta z tego wskaźnika, próbując odczytać dane. Opisana wyżej sytuacja będzie powodować błędy? Bo przecież magicznie nie zmienią się wartości pointerów?

Aktualnie, zakładając, że taki problem może wystąpić nadaję każdemu elementowi wektora unikalną nazwę i przesyłam między klasami wyłącznie nazwę, następnie gdy chcę użyć tego obiektu to wyszukuję go sobie po nazwie. Oczywiście wydaje mi się to brzydkie i mało eleganckie. Czy rzeczywiście istnieje ryzyko wyżej opisanego przypadku? Czy dotyczy to wszystkich kontenerów z stl? (przypuszczam, że wszystko co jest oparte o listę tego problemu nie posiada, z racji braku potrzeby realokacji zasobów listy?).

1

Istnieje takie ryzysko, dlatego tez bezsensowna jest instrukcja:

TYP* ptr = my_vector[3];

w celu zrobienia alias na ten obiekt.
Po to wlasnie tam jest operator indeksowania, zeby do konkretnego obiektu odwolywac sie bez dodatkowych rzeczy.
Druga sprawa mozna skorzystac z iteratorow.

Co do reszty kontenerow odsylam do dokumentacji.

1

Dlatego powinieneś w tej sytuacji korzystać z boost::stable_vector. Tu jest wszystko wyjaśnione, dlaczego tak się dzieje:
http://www.boost.org/doc/libs/1_53_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.stable_vector

1

Mam dużą liczbę ciężkich obiektów upchniętych na wektorze, dlatego między klasami przesyłam jedynie wskaźnik na dany element.

  1. przesyłaj wskaźnik lub referencję na wektor, oraz indeks do wektora, albo
  2. trzymaj w wektorze nie obiekty ale wskaźniki na obiekty (tutaj trzeba niestety bardzo pilnować ręcznego zwalniania)

nadaję każdemu elementowi wektora unikalną nazwę i przesyłam między klasami wyłącznie nazwę, następnie gdy chcę użyć tego obiektu to wyszukuję go sobie po nazwie.
Tracisz czas, bo jest na to gotowiec std::map :-)

1

najprostszym rozwiązaniem jest wywołanie reserve z wartością, która zapewni, że realokacja zawartości vector nie będzie potrzebna przez cały czas działania programu.

nakome napisał(a):

Mam dużą liczbę ciężkich obiektów upchniętych na wektorze, dlatego między klasami przesyłam jedynie wskaźnik na dany element.

W takim razie drugim rozsądnym rozwiązaniem, jest tworzenie każdego elementu na stercie, a w vector trzymać (mądre) wskaźniki na twoje obiekty, wówczas realokacja vector nie będzie unieważniać wskaźników do tych obiektów.

Trzecim rozwiązaniem jest lista.

0

Wygląda na to, że trzymanie wskaźników zamiast obiektów będzie najprostsze i eliminujące problem. Dziękuję.

1 użytkowników online, w tym zalogowanych: 0, gości: 1