• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

c++ vektor vektorów

VPS Starter Arubacloud
0 głosów
297 wizyt
pytanie zadane 27 kwietnia 2017 w C i C++ przez jankustosz1 Nałogowiec (35,880 p.)

Witam.

vector<vector<int>> tab;
tab.push_back(vector<int>());

Takie kod jest bezpieczny? Nowoutworzony jest cały czas zarezerwowany w pamięci, czy jest zwalniany i odwoływanie się do niego to korzystanie z nieswojej pamięci? Czy jak zacznę dynamicznie tworzyć zmienny nie no nadpiszą się na jego miejscu?

To chyba podobna sytuacja jak taka: (ten przykład wiem że jest błędny)

int &test()
{
  int a;
  return a; 
}

 

1 odpowiedź

0 głosów
odpowiedź 27 kwietnia 2017 przez criss Mędrzec (172,590 p.)
edycja 29 kwietnia 2017 przez criss
 
Najlepsza

Tak, ten kod jest w pełni poprawny. Ale niewiele zrozumiałem z reszty tego co napisałeś; szczególnie tego:

Czy jak zacznę dynamicznie tworzyć zmienny nie no nadpiszą się na jego miejscu?

Anyway push_back przyjmuje obiekt i w vectorze umieszcza jego kopie. Nie wiem czy tego dotyczyły twoje obawy, ale: W żaden sposób to nie jest sytuacja podobna do drugiego kodu.

komentarz 27 kwietnia 2017 przez jankustosz1 Nałogowiec (35,880 p.)
push back przyjmuje referencje, chyba nie robi kopi, czy robi?

Czy jak zacznę dynamicznie tworzyć zmienny nie no nadpiszą się na jego miejscu?

Poprawione: Czy jak zacznę dynamicznie tworzyć zmienne nie nadpiszą się na jego miejscu (jego w sensie tego vectora)?
komentarz 27 kwietnia 2017 przez criss Mędrzec (172,590 p.)
Robi kopie. To właśnie miałem na myśli poprzez "i w vectorze umieszcza jego kopie" :D Z resztą inaczej w ogóle nie miało by to prawa działać.
komentarz 27 kwietnia 2017 przez jankustosz1 Nałogowiec (35,880 p.)
Zasugerowałem się tym że bierze to referencję. Ale to w takim razie po co bierze referencję skoro może wziąć bez referencji i wtedy byłoby oczywiste że robi kopię.
komentarz 27 kwietnia 2017 przez criss Mędrzec (172,590 p.)

Ponieważ:

  • wtedy musiałby robić dwie kopie: jedną do zainicjalizowania argumentu i drugą do zainicjalizowania obiektu który znajdzie się w vectorze
  • nie każdy obiekt jest kopiowalny. Wtedy pozostaje nam przeładowana "wersja" push_back przyjmująca rvalue reference i nasz obiekt zostanie przekopiowany przy użyciu tzw. przenoszenia (move semantics)

Powodów pewnie jest więcej, ale te pierwsze mi przyszły do głowy.

komentarz 27 kwietnia 2017 przez jankustosz1 Nałogowiec (35,880 p.)

Nie wiem jak zbudowany jest w środku vector, ale mógłby zawierać tablicę referencji danego typu np. vector<int> mógłby zawierać prywatną referencję int& tab[], wtedy jakby się wysyłało przez wartość(czyli push back przyjmuje kopię argumentu a nie referencję) to nie robiłby w środku kopi tylko ustawiał referencję. Wtedy kopia zrobiłaby się tylko raz przy wysyłaniu argumentu do funkcji.(Dla zwykłego programisty nie jest oczywiste jak to w środku działa). Czyli ten pierwszy powód nie jest do końca taki pewny.

Ta funkcja przeładowana jest chyba tylko w c++11, coś chyba jestem nie douczony bo pierwszy raz widzę referencję do referencji, jak przesłać zmienną przez to przeładowanie?

void push_back (value_type&& val);

 

komentarz 28 kwietnia 2017 przez criss Mędrzec (172,590 p.)
edycja 29 kwietnia 2017 przez criss

mógłby zawierać tablicę referencji danego typu np. vector<int> mógłby zawierać prywatną referencję int& tab[]

Nie, to nie jest możliwe. I przy okazji strasznie niepraktyczne.

(Dla zwykłego programisty nie jest oczywiste jak to w środku działa)

Raczej powinno być. Oczywiście nie mówię, że to źle, że tego teraz nie wiesz. Wszystko z czasem, ale programista powinien mniej-więcej orientować się jak działają kontenery, żeby móc odpowiednio dobierać w zależności od sytuacji.

 Ta funkcja przeładowana jest chyba tylko w c++11

Tak, bo dopiero od C++11 mamy rvalue referencje.

 coś chyba jestem nie douczony bo pierwszy raz widzę referencję do referencji

To nie jest referencja do referencji :D Dwoma ampersandami przy nazwie typu oznacza się wspomniane już tzw. rvalue referencje. Została wprowadzona po to, żeby móc rozróżniać kiedy funkcja dostaje lvalue, a kiedy rvalue (obiekt tymczasowy) które może nieco inaczej potraktować przy kopiowaniu. Np. na przykładzie vectora jako argumentu pewnej funkcji: wiedząc, że jest to obiekt tymczasowy możemy jedynie przekazać z jednego obiektu do jego kopii wskaźnik na jego wewnętrzną tablice, skoro wiemy, że obiekt tymczasowy i tak za chwile zostanie zniszczony i tablica zostałaby zwolniona. Także zamiast alokować nową tablice i przekopiowywać zawartość starej do nowej, zwyczajnie przenosimy wskaźnik i sprawiamy, żeby obiekt tymczasowy przy destrukcji jej nie zwolnił (bo już należy do nowego obiektu).

jak przesłać zmienną przez to przeładowanie?

Przeładowanie z rvalue referencją zostanie wywołane jeśli argumentem przekazywanym do wywołania będzie rvalue. Dodatkowo możemy wymuszać potraktowanie obiektu/zmiennej jako rvalue nawet jeśli nią nie jest dzięki std::move.

Live przykład 

komentarz 28 kwietnia 2017 przez mokrowski Mędrzec (155,460 p.)
Standard C++ wymaga aby dane w vector  były alokowane w ciągłej przestrzeni danych tak więc dane trafiają do tablicy :-) Dostęp do "surowej przestrzeni danych" w vector (czyli tablicy), masz z użyciem .data: http://en.cppreference.com/w/cpp/container/vector/data. Nie znaczy to wcale że masz "modyfikować bezrefleksyjnie" te dane :-)

Jeśli chcesz uniknąć tworzenia obiektu w trakcie dodawania do vector, możesz użyć emplace_back(...).

Podobne pytania

+1 głos
1 odpowiedź 138 wizyt
pytanie zadane 22 czerwca 2015 w C i C++ przez Wiciorny Ekspert (269,120 p.)
0 głosów
1 odpowiedź 84 wizyt
pytanie zadane 28 maja 2020 w C i C++ przez persikk Obywatel (1,140 p.)
0 głosów
3 odpowiedzi 608 wizyt
pytanie zadane 1 czerwca 2015 w C i C++ przez Barbas Nowicjusz (120 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...