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

Wskaźniki i referencje razem. Czy to co robię jest bezpieczne?

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
0 głosów
285 wizyt
pytanie zadane 22 marca 2018 w Offtop przez Marcin Siniarski Gaduła (4,420 p.)

Postanowiłem pobawić się z wskaźnikami i referencjami naraz. Jak na razie wszystko jest dobrze, jednak chce się dowiedzieć trochę więcej.
Aktualnie eksperymentuje razem z klasami.

Oto dotychczasowy rezultat:

#include <iostream>

template<typename T>
class Vector{
  public:
  Vector(T init_x, T init_y, T init_z)
    :x(init_x),y(init_y),z(init_z){

  }
  T getX(){return x;}
  T getY(){return y;}
  T getZ(){return z;}
  void setX(T newX){this->x=newX;}
  void setY(T newY){this->y=newY;}
  void setZ(T newZ){this->z=newZ;}
  private:
  T x,y,z;
};

template <typename T> void referencePtr(T *&ptrRef);

int main(int argc, char* argv[]){
  Vector<int>* vct = new Vector<int>(0,0,0);
  int *z = new int(vct->getZ());
  referencePtr(z);
  vct->setZ(*z);
  std::cout << vct->getZ() << std::endl;
  std::cin.get();
  delete z;
  delete vct;
  return 0;
}
template <typename T> void referencePtr(T *&ptrRef){
  *ptrRef += 1;
}

 

1 odpowiedź

+2 głosów
odpowiedź 22 marca 2018 przez Sebastian Fojcik Nałogowiec (43,040 p.)
wybrane 23 marca 2018 przez Marcin Siniarski
 
Najlepsza

Wszystko jest w jak najlepszym porządku. Jak przesyłasz wskaźnik do funkcji, to oczywiście domyślnie wskaźnik przekazywany jest przez wartość (sam wskaźnik jako zmienna zajmuje miejsce w pamięci). U Ciebie z tego co widzę funkcja (a w zasadzie jej szablon) przyjmuje referencję do wskaźnika. Czyli nie tworzysz na stosie nowego wskaźnika.

Jednak w przypadku Twojej funkcji, ta referencja nie ma wpływu na nic innego. Tak samo zadziała program bez referencji. Przesyłanie wskaźnika przez referencje umożliwia to, aby w funkcji przestawić ten wskaźnik na coś innego (albo przyspieszyć nieco wywołanie funkcji). Czyli w swojej funkcji mógłbyś np. zarezerwować nową pamięć na wskaźnik podany jako argument wywołania, a tę obecnie zarezerwowaną zwolnić. Wtedy przesłanie wskaźnika w referencji byłoby konieczne.

Musisz też być świadomy konsekwencji przesyłania, już nawet nie wskaźnika, ale czegokolwiek przez referencję. Spójrz na poniższy kod:

void f( int * &wsk )
{
	*wsk += 1;
}

int main()
{
	int n = 5;
	int * wsk = &n;
	cout << *wsk << endl; // 5
	f( wsk );
	cout << *wsk << endl; // 6

	return 0;
}

Rezultat oczywiście do przewidzenia. Ale popatrz co jest niemożliwe przez to, że funkcja przyjmuje referencję:

void f( int * &wsk )
{
	*wsk += 1;
}

int main()
{
	int n = 5;
	int * wsk = &n;
	cout << *wsk << endl; // 5
	f( &n );    // BŁĄD !!!
	cout << *wsk << endl;

	return 0;
}

Gdyby funkcja przyjmowała zwykły wskaźnik, a nie referencję do niego, to wywołanie &n byłoby możliwe. W tym przypadku odbierasz sobie to prawo.

void f( int * wsk )
{
	*wsk += 1;
}

int main()
{
	int n = 5;
	int * wsk = &n;
	cout << *wsk << endl; // 5
	f( &n );    // OK
	cout << *wsk << endl; // 6

	return 0;
}

Jeśli miałbym skomentować to, co wyprawiasz wewnątrz main. Cóż, ciężko coś sensownego skomentować, bo widać, że kod, który wysłałeś jest mocno dydaktyczny. W sensie: żaden programista nie pisałby tego wszystkiego, aby zwiększyć współrzędną z o jeden :-P
Aczkolwiek kod jest poprawny, tylko bardzo dziwnie i ryzykownie napisany. Np. tworzysz dynamicznie zmienną:

int *z = new int(vct->getZ());

Tylko po to, aby ją zwiększyć o jeden, nadpisać przy jej pomocy współrzędną z i skasować.
Jakbyś nie mógł napisać czegoś takiego:

vct->setZ( vct->getZ()+1 );

Ale nie czepiam się. Rozumiem, że Twój przykład jest tylko dydaktyczny ;-)

Jak tak teraz patrzę, to nie zadałeś nawet konkretnego pytania, więc mam tylko nadzieję, że udzieliłem choć trochę oczekiwanej odpowiedzi :-)

komentarz 23 marca 2018 przez Marcin Siniarski Gaduła (4,420 p.)

Wiem, moje użycie wskaźnika *z jest praktycznie bezcelowe, lecz funkcja oczekuje wskaźnika, a nie liczby lub obiektu.

 

Rezultat oczywiście do przewidzenia. Ale popatrz co jest niemożliwe przez to, że funkcja przyjmuje referencję:
[...]
 f( &n );    // BŁĄD !!!

 To akurat wiem. Referencja sama pobiera adres liczby dlatego jest błąd. C++ musi wiedzieć (uwaga, tak sobie wyjaśniam jak działają referencje) gdzie dopisać drugą nazwę do adresu zmiennej.

Dziękuję za wyjaśnienie oraz rozpisanie się na ten temat :-)

Podobne pytania

0 głosów
0 odpowiedzi 193 wizyt
pytanie zadane 15 marca 2016 w C i C++ przez falauthy Stary wyjadacz (11,550 p.)
0 głosów
3 odpowiedzi 1,084 wizyt
pytanie zadane 18 lipca 2018 w C i C++ przez Nowacx02 Obywatel (1,060 p.)
0 głosów
1 odpowiedź 3,679 wizyt
pytanie zadane 4 marca 2018 w C i C++ przez bartez86 Nowicjusz (220 p.)

93,430 zapytań

142,427 odpowiedzi

322,652 komentarzy

62,794 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

...