Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [C++] Wskaźniki
Forum PHP.pl > Inne > Hydepark
Ether
Witam,

Mógłby mi ktoś wytłumaczyć dla czego np w tym kodzie http://wklej.org/hash/d3c96651cb0/ użyto wskaźnika i jak on naprawdę działa?
Ogarniałem Już Wszystkie Poradniki z Google i po Części wiem tylko Że np jest int cos=1; i int *w; int cos2 = &cos; to cos2 jest adresem tak? Plx help bo stoje na tym narazie i nie moge sie dalej uczyc ^^
Pozdrawiam
mar1aczi
Chodzi Ci zapewne o *wylosowane. Wskaźnik użyty jest dlatego, że z góry nie wiadomo ile będzie losowań. Wskaźnik to taka dynamiczna tablica.
W przykładzie jest pewne uproszczenie - na jego początku deklarujesz ilość losowań, ale gdyby go przerobić, że to użytkownik decyduje o ilości, w chwili kompilacji rozmiar tablicy będzie nieznany.
pyro
Cytat(Ether @ 8.04.2015, 02:35:26 ) *
Witam,

Mógłby mi ktoś wytłumaczyć dla czego np w tym kodzie http://wklej.org/hash/d3c96651cb0/ użyto wskaźnika i jak on naprawdę działa?
Ogarniałem Już Wszystkie Poradniki z Google i po Części wiem tylko Że np jest int cos=1; i int *w; int cos2 = &cos; to cos2 jest adresem tak? Plx help bo stoje na tym narazie i nie moge sie dalej uczyc ^^
Pozdrawiam


Jak zwyczajnie deklarujesz tablicę, to kompilator w C++ musi znać jej rozmiar i możesz to zrobić poprzez ręczne wpisanie rozmiaru tablicy albo np. podając zadeklarowaną stałą jako jej rozmiar. W przykładzie z losowaniem nie wiesz podczas kompilacji ile będzie losowań, bo będziesz dopiero o to pytał użytkownika po skompilowaniu programu, dlatego musisz użyć wskaźnika, który wskazuje na tablicę intów. Dobrym zwyczajem jest czyszczenie pamięci po użyciu wskaźnika, czego w w/w kodzie nie zrobiono:

Kod
delete[] wylosowane;


Natomiast drobne przykłady co do samych wskaźników:

Kod
// Deklaracja zmiennej int o wartości 2
int cos=2
// Wskazanie wskaźnikowi adresu zmiennej coś i wyświetlenie go
int* cosPtr = &cos;
std::cout<<cosPtr;
// Przypisanie nowej zmiennej zawartości cos (operator dereferencji - odwołanie się do zawartościu spod adresu, na który wskazuje wskaźnik) i wyświetlenie
int abc = *cos;
std::cout<<abc;
com
@up to nie jest dobry zwyczaj, to konieczność bo inaczej są wycieki pamięci smile.gif
Posio
@Pyro
  1. delete[] wylosowane;


btw.
najpierw należy przeleciec po tablicy i usunąc każdego zadeklarowaego inta...
pyro
@Posio, nie.

"Jeśli natomiast przydzieliliśmy pamięć z użyciem parametru określającego ilość elementów tablicy to musimy poinformować operator delete o tym, że wskaźnik wskazywał na tablicę rekordów. Aby to zrobić dopisujemy zaraz za operatorem nawiasy kwadratowe []. Nie podajemy jednak w nich rozmiaru tablicy, ponieważ operator ten sam ustala rozmiar bloku jaki został przydzielony, a następnie go usuwa z pamięci. Składnia tej operacji wygląda następująco:

C/C++
delete[] wskaznik_do_tablicy;"

Źródło: http://cpp0x.pl/kursy/Kurs-C++/Dynamiczne-...ew-i-delete/307

// ADD

albo inaczej:

Cytat
operator delete[] is a regular function that can be called explicitly just as any other function. But in C++, delete[] is an operator with a very specific behavior: An expression with the delete[] operator, first calls the appropriate destructors for each element in the array (if these are of a class type), and then calls an array deallocation function.


Źródło: http://www.cplusplus.com/reference/new/ope...20delete%5B%5D/
solificati
Albo jak człowiek piszemy własny alokator pamięci, używamy raii i korzystamy tylko z inteligentnych wskaźników.

A dlaczego tu jest wskaźnik? Bo new T zwraca T*. W rozumieniu C, tablica jest *prawie* jak wskaźnik na pierwszy element tablicy. W C++ jest więcej *prawie*, ale idea jest ta sama.
r4xz
Cytat(solificati @ 8.04.2015, 13:15:14 ) *
W rozumieniu C, tablica jest *prawie* jak wskaźnik na pierwszy element tablicy. W C++ jest więcej *prawie*, ale idea jest ta sama.

Możesz rozwinąć? A najlepiej podaj przykład, ponieważ to co piszesz póki co jest tylko pisaniem bez konkretów i mimo doświadczenia w c/c++ kompletnie nie mam pojęcia co ty możesz mieć na myśli...
pyro
Cytat(r4xz @ 8.04.2015, 18:02:48 ) *
Możesz rozwinąć? A najlepiej podaj przykład, ponieważ to co piszesz póki co jest tylko pisaniem bez konkretów i mimo doświadczenia w c/c++ kompletnie nie mam pojęcia co ty możesz mieć na myśli...


Kolega raczej plecie farmazony. Pewnie chodziło mu o coś takiego:

Kod
#include <iostream>

int main()
{
    const int N = 3;

    int tab[N];

    tab[0] = 5;
    tab[1] = 10;
    tab[2] = 15;

    int* wsk = tab;

    std::cout<<*tab<<std::endl; // 5
    // tab++;   ->   to by spowodowalo blad
    std::cout<<*wsk<<std::endl; // 5
    wsk++;
    std::cout<<*wsk<<std::endl; // 10
    wsk++;
    std::cout<<*wsk<<std::endl; // 15

    std::cout<<std::endl;
    std::system("pause");
    return 1;


}


Ale pierwsze i najbardziej podstawowe pytanie brzmi: Co to ma do tematu?
solificati
Identyfikator tablicy wartości typu T może występować w tych samych sytuacjach jako wartość rvalue jak wskaźnik na zmienną typu T. W wypadku tablicy wartość ta jest adresem w pamięci pierwszego elementu tablicy. To jest zresztą podstawa intuicji, że mallociem tworzy się "dynamiczne" tablice. Większość tych "prawie" dotyczy statycznych tablic, bo kompilator może iść na skróty w generowaniu kodu maszynowego i wygląda on wtedy minimalnie inaczej.

Cytat(pyro @ 8.04.2015, 20:42:40 ) *
Kod
    std::cout<<*tab<<std::endl; // 5
    // tab++;   ->   to by spowodowalo blad

Bo identyfikator tablicy nie może występować jako lvalue.
pyro
Cytat(solificati @ 8.04.2015, 20:50:40 ) *
Bo identyfikator tablicy nie może występować jako lvalue.


No brawo, ale co z tego? Niebo jest nad nami, bo mleko jest białe biggrin.gif ?

Podpinam się pod @r4xz
solificati
Wszystkie trzy rzeczy, czyli niemodyfikowalność jako rvalue, adres identyfikatora podczas statycznej analizy oraz inne zachowanie w sizeof i spółce dla mnie mieści się w "prawie". Poza tym identyfikator i wskaźnik zachowują się identycznie, często identyfikator jest rozkładany na wskaźnik, co powoduje generowanie identycznego kodu. Abstrakcja ta jest spójna i wygodna. Albo czegoś nie rozumiesz albo bawisz się w zbędny puryzm.
pyro
@solificati przed napisaniem posta w jakimkolwiek temacie, warto zużyć trochę swojej many na zaklęcie, które pozwoli Ci na przeczytanie o czym on jest.
solificati
Kod
int *wylosowane = new int[ilosc_losowan+1]


Cytat
Dlaczego [...] użyto wskaźnika i jak on naprawdę działa?


Cytat
A dlaczego tu jest wskaźnik? Bo new T zwraca T*. W rozumieniu C, tablica jest *prawie* jak wskaźnik na pierwszy element tablicy. W C++ jest więcej *prawie*, ale idea jest ta sama.


Możesz mi zarzucić, że nie wdałem się w szczegóły (dlaczego użyto new? Ty napisałeś wcześniej, żaden z nas też nie wdawał się w szczegóły o stercie i stosie oraz o tym, że ten kod wcale nie wymaga new, bo rozmiar jest znany podczas kompilacji (inaczej niż pisałeś) i z rozszerzeniem VLS albo constexpr, new byłby niepotrzebny), ale napisałem "dlaczego" i "jak działa".
Ja bym sobie wystawił niezłą ocenę. Twoje "farmazony, mleka i zaklęcia" jednak poniżej średniej.
Ether
jak robie rekurencje statycznych funkcji polimorficznych to wskazniki w funkcjach tez ulegają zmianie adresu?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.