Stos vs sterta - wskaźniki

0

Witam,
mam następujące pytania:

  1. czy każda zmienna utworzona w funkcji, ale bez pomocy operatora new będzie utworzona na stosie?
  2. Czy każda zmienna utworzona globalnie lub operatorem new będzie utworzona na stercie?
  3. Czy metoda (funkcja w klasie), w której są tworzone zmienne lokalne, będzie tworzyć je również na stosie - nawet, gdyby obiekt danej klasy był utworzony na stercie?
  4. Czy tworząc wskaźnik na stosie (w funkcji) do obiektu utworzonego na stercie (globalnie) inny obiekt utworzony na stercie (globalnie) posiadający wskaźnik do tego wskaźnika na stosie będzie się odwoływał szybciej, w przeciwieństwie, gdyby oba wskaźniki były utworzone na stercie? Chodzi o coś w stylu:
    void f() {
    K* wskaznik; 
    g_obiekt.set_ptr(&wskaznik); /*g_obiekt to obiekt globalny lub pole innego obiektu - wewnątrz którego jest wskaźnik na ten wskaźnik utworzony w metodzie f()*/
    //...
    }
  5. Wydaje mi się, że tak, ale dla pewności zapytam: czy można w ogóle bezpiecznie utworzyć wskaźnik na stosie (w funkcji) do obiektu na stercie i na nim operować?

Z góry dziękuję za odpowiedzi.

1
  1. Nie, wyjątkiem są zmienne static
  2. Nie, zwykle to jest data segment.
  3. Tak
  4. Nie bardzo rozumiem pytanie, ale: nie
  5. Jasne że można bo i czemu niby nie? Co to znaczy "bezpiecznie"?
7

W C++ nie ma żadnych stosów i stert. To kwestia implementacji.

W C++ jest storage duration. To jest właściwość obiektu. Storage duration może być:

  • static (statyczne)
  • thread (związane z wątkiem)
  • automatic (automatyczne, to jest kojarzone ze stosem)
  • dynamic (dynamiczne, to jest kojarzone ze stertą)

Każdy obiekt, który ma zakres bloku (upraszczając: jest po prostu w funkcji) i nie ma przy nim słów kluczowych static albo extern ma automatic storage duration. To jest to, co popularne nazywa się stosem.

Każdy obiekt utworzony za pomocą wyrażenia z operatorem new ma dynamic storage duration. To jest to, co popularnie nazywa się stertą. Operator new nie zwraca tego obiektu, a jedynie jego adres. Tzn:

int *v = nullptr // obiekt v (wskaźnik do int), który ma automatic storage duration
v = new int{}; // new tworzy obiekt, który ma dynamic storage duration i zapisuje jego adres do obiektu v, który nadal jest automatic

Każdy obiekt, który nie ma dynamic storage duration ani thread storage duration oraz nie jest lokalny dla bloku (upraszczając: nie jest wewnątrz funkcji) ma static storage duration. Dodatkowo można nadać obiektowi static storage duration za pomocą słowa kluczowego static.

Zgodnie z powyższym:

  1. Każda taka zmienna będzie miała automatic storage duration, chyba, że będzie przy niej static albo extern.
  2. Nie. Zmienne globalne mają static storage duration, utworzone za pomocą operatora new - dynamic storage duration.
  3. Tak. To jaki storage duration ma obiekt wskazywany przez this nie ma żadnego znaczenia.
  4. Nic z tego nie rozumiem, ale jak piszesz "czy szybciej" to odpowiedam: użyj profilera i zobacz.
  5. To jest konieczność ponieważ new zwraca wskaźnik i trzeba go gdzieś zapisać.
0

Dzięki @Shalom
W tym 4 pytaniu chodzi o taką sytuację:
Mam dużą tablicę (vector) utworzony globalnie - czyli na stercie.
Mam również obiekt (powiedzmy, że utworzony również globalnie), który ma wskaźnik na dany element tej tablicy.
W funkcji natomiast bardzo często operuję na tym wskaźniku tj. np. iteruję po części tego wektora (odnoszę się do elementów tego vectora).
No i rozważam żeby zamiast robić w tym obiekcie wskaźnik na dany element tego vectora nie zrobić w funkcji takiego wskaźnika (który byłby na stosie) a w obiekcie zrobić wskaźnik na wskaźnik.
No i zastanawiam się, czy teoretycznie to powinno przyśpieszyć działanie programu?

0
<quote="1164036">4. Czy tworząc wskaźnik na stosie (w funkcji) do obiektu utworzonego na stercie (globalnie) inny obiekt utworzony na stercie (globalnie) posiadający wskaźnik do tego wskaźnika na stosie będzie się odwoływał szybciej, w przeciwieństwie, gdyby oba wskaźniki były utworzone na stercie? Chodzi o coś w stylu: ```cpp void f() { K* wskaznik; g_obiekt.set_ptr(&wskaznik); /*g_obiekt to obiekt globalny lub pole innego obiektu - wewnątrz którego jest wskaźnik na ten wskaźnik utworzony w metodzie f()*/ //... } ``` Wskaźnik to wskaźnik - efektywność jest taka sama, niezależnie od położenia w ram. > ##### [Kofcio napisał(a)](http://4programmers.net/Forum/1164036): > 5. Wydaje mi się, że tak, ale dla pewności zapytam: czy można w ogóle bezpiecznie utworzyć wskaźnik na stosie (w funkcji) do obiektu na stercie i na nim operować? Tak. Najwyraźniej masz poważne tyły natury ogólnej... jak każdy amator, wirtualny programista, wychowany na visualach.
0

Czy tworząc wskaźnik na stosie (w funkcji) do obiektu utworzonego na stercie (globalnie) inny obiekt utworzony na stercie (globalnie) posiadający wskaźnik do tego wskaźnika na stosie będzie się odwoływał szybciej, w przeciwieństwie, gdyby oba wskaźniki były utworzone na stercie?

Masło maślane.... Wskaźnik jako zmienna - może leżeć na stosie, ale można za pomocą jego alokować miejsce na stercie.

Wskaźnik to wskaźnik - efektywność jest taka sama, niezależnie od położenia w ram.

Umieszczanie zmiennych na stosie jest szybsze niż dynamiczna alokacja na stercie.

0

Nie wiem na czym jesteś "wychowany", ale więkość twoich technicznych wypowiedzi to brednie. - spartanPAGE

Ależ ja nie jestem wychowany na czymkolwiek...
no, po prostu: 40 lat praktyki robi swoje... :)

1
Kofcio napisał(a):
  1. Wydaje mi się, że tak, ale dla pewności zapytam: czy można w ogóle bezpiecznie utworzyć wskaźnik na stosie (w funkcji) do obiektu na stercie i na nim operować?

Można - o ile ten wskaźnik nie jest dalej nigdzie przekazywany (przez return, parametr wyjściowy lub pole w obiekcie).
Wydajnościowo bez sensu, ale różne są wymagania czasami.

Z drugiej strony w celach optymalizacji, robi się czasami coś odwrotnego - do lokalnego wskaźnika (na stercie) zapisuje wskaźnik do obiektu z atrybutu klasy lub zmiennej globalnej.
Może być szybsze (warto zajrzeć do ASM i/lub sprofilować).

0

Programista z 40 letnim doświadczeniem praktyki byłby rozważniejszy w dobieraniu słów, i miałby już dawno nabite z kilkaset postów na tym forum, a nie, że pisze jako guest. - Dawid90dd dzisiaj, 02:13

Ależ jestem tu logowany, tyle że się nie loguję... tak od około 10 lat.

Pamiętam nawet czasy gdy, np. Azerian, był tu... szczeniaczkiem. :)

0
vpiotr napisał(a):

Z drugiej strony w celach optymalizacji, robi się czasami coś odwrotnego - do lokalnego wskaźnika (na stercie) zapisuje wskaźnik do obiektu z atrybutu klasy lub zmiennej globalnej.
Może być szybsze (warto zajrzeć do ASM i/lub sprofilować).

@Vpiotr czy mógłbym Cię prosić o rozwinięcie tego, bo trochę tego nie rozumiem, a nie ukrywam, że moje dociekania wynikają właśnie z chęci optymalizacji.

vpiotr napisał(a):

do lokalnego wskaźnika (na stercie)

Czy "lokalny wskaźnik" nie powinien być na stosie?
Chodzi Ci o utworzenie wskaźnika globalnie (na stercie) czy lokalnie wewnątrz funkcji (na stosie)?

vpiotr napisał(a):

zapisuje wskaźnik do obiektu z atrybutu klasy lub zmiennej globalnej.

Czyli wskaźnik na wskaźnik?

Czy mógłbyś podać jakiś prosty przykład?
Z góry dziękuję za pomoc!

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