Structură simplă a datelor

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită pe 20 noiembrie 2013; verificările necesită 58 de modificări .

O structură de date simplă ( de exemplu , date vechi simple , POD ) este  un tip de date în limbaje moderne de programare de nivel înalt, care are o aranjare rigidă a câmpurilor în memorie care nu necesită restricții de acces și control automat . Variabilele de acest tip pot fi copiate cu rutine simple de copiere în memorie precum . Opusul este o structură de date gestionată . memcpy

Cel mai simplu mod de a defini o structură de date simplă este prin contradicție. Dacă compilatorul rearanjează în secret câmpurile de la utilizator sau când creează o structură de date, apelează în secret constructorul sau apelează destructorul atunci când structura este distrusă sau la copiere - o procedură specială de copiere, atunci aceasta este o procedură gestionată (adică , nu simplă) structură.

Beneficiile structurilor de date simple

Structurile simple de date au două caracteristici.

Dispozitiv previzibil în memorie

Compilatorul poate reconstrui automat structura datelor la discreția sa (de exemplu, schimba ordinea câmpurilor. În limbajul C++, acest lucru este posibil numai dacă există o etichetă de acces public/privat/protejat între câmpuri. O secvență de câmpuri care nu sunt separate printr-o astfel de etichetă trebuie să fie plasate în memorie în ordinea declarației de câmp). O astfel de restructurare poate economisi serios memorie, dar rupe compatibilitatea. În POD-uri, această optimizare este dezactivată.

Cu alte cuvinte: tipurile marcate POD sunt aranjate în memorie exact așa cum a descris programatorul (poate cu o anumită aliniere ). Prin urmare, numai POD-urile pot fi folosite pentru a comunica între două biblioteci de rulare . În special, pentru a transfera date de la program la program, de la plugin la plugin, pentru a comunica cu cod scris într-un alt limbaj de programare . Pentru a scrie rapid un antet de fișier complex, cum ar fi BMP , pe disc , îl puteți forma în memorie și apoi îl puteți scrie cu o singură comandă - dar structura de date în care formăm antetul trebuie să fie și un POD.

Fără cod de control

Aceasta înseamnă că atunci când apare un obiect, nu trebuie să apelați constructorul, atunci când copiați, operația de atribuire și când distrugeți, destructorul. Aceasta, la rândul său, oferă următoarele beneficii:

  1. Inițializare statică. În loc să apelați constructorul ascuns de programator la pornirea programului , POD-urile pot fi asamblate în timp ce programul este compilat.
  2. Copiere banală (inclusiv copierea matricelor) prin funcții precum memcpy.
  3. Din nou, acest lucru este important pentru comunicarea între programe: la urma urmei , managerul de memorie nu ar trebui să gestioneze memoria care nu îi aparține.
  4. Doar tipurile simple pot fi în union(în Pascal, respectiv record/case).
  5. Funcțiile cu efecte secundare (cum ar fi funcțiile de sistem care afectează rezultatul unui apel ulterior GetLastError[1] ) sunt slab compatibile cu tipurile gestionate automat.

Limbi în care toate tipurile sunt simple

În C++

În C++ , POD este definit prin contradicție. Un tip de date este un POD dacă:

Conform standardului C++, un tip de date simplu este structurat exact așa cum este descris (și este pe deplin compatibil octet cu octet în aspectul memoriei cu o structură C). Compilatorul poate reorganiza structura gestionată în modul pe care îl consideră cel mai eficient.

Definiție POD pre-C++11:

Un agregat este fie o matrice, fie o clasă care nu are:

Un agregat poate fi inițializat (ca în C) cu o listă de forma = {1, 2, 3};

Scalarul se numește:

(adică un tip care nu este o clasă, o matrice sau o referință)

Un POD este fie un scalar , fie o matrice de alte POD-uri, fie o clasă care este un agregat și, în plus:

În C++11

„Dispozitiv previzibil în memorie” și „fără cod de control” sunt proprietăți de tip similare, dar diferite. De exemplu, structura de date STRRET[ 2] , care în Windows este folosită pentru a trece șiruri de caractere de la un manager de memorie la altul, poate fi „ înfășurată ” în cod de control, dar a doua proprietate, dispozitivul previzibil, rămâne. Prin urmare, conceptul de POD-uri în C++11 este împărțit în trei.

O clasă se numește „avand un constructor de copie trivial” dacă toate următoarele sunt adevărate:

Constructorul de copiere trivial generat automat este memmove().

Termenii „având un constructor implicit banal/operator de atribuire/constructor de mutare/operator de mutare” sunt definiți exact în același mod.

O clasă se numește „având un destructor trivial” dacă toate următoarele sunt adevărate:

O astfel de clasă nu necesită distrugere, iar memoria care o conține poate fi dealocată fără a fi curățată.

Se spune că o clasă este „trivial copiabilă” dacă toate funcțiile membre speciale de mai sus sunt banale (cu excepția constructorului implicit, care poate fi non-trivial). Scalarii, precum și matricele de obiecte care pot fi copiate trivial, sunt, de asemenea, copiabile. Astfel de tipuri pot fi copiate prin memcpy.

O clasă se numește „trivial” dacă este trivial copiabilă și are, de asemenea, un constructor implicit trivial.

Cu alte cuvinte, o clasă este trivială dacă are:

O clasă este un tip de dispozitiv standard dacă:

Să clarificăm ultima condiție: în limbaj nu pot exista două obiecte diferite de același tip cu aceeași adresă, ceea ce înseamnă că dimensiunea unei clase goale (fără câmpuri nestatice) nu poate fi 0 (cel puțin 1). Cu toate acestea, se face o excepție pentru „partea B din clasa D : B” iar dimensiunea acesteia (dacă este goală) poate fi strict zero, rezultând că nu există „completare” între începutul lui D și primul său câmp. Dar, în același timp, dacă tipul primului câmp este și B, excepția nu poate fi aplicată, deoarece (B *) & d și & (d. câmp 1) indică obiecte diferite de același tip și, prin urmare, " căptușeală” este necesară. Ultima condiție din lista de mai sus nu înseamnă altceva decât „în clasele unui dispozitiv standard, o astfel de garnitură este interzisă”.

Astfel de tipuri au un dispozitiv previzibil în memorie (de exemplu, adresa unui obiect în ansamblu este aceeași cu adresa primului său câmp, desigur, după reinterpret_cast la același tip, de exemplu, pentru a anula *), pot să fie trecut la o altă bibliotecă de rulare și la programare în alte limbaje.

Apoi POD  este o matrice de alte POD-uri, sau un scalar, sau o clasă trivială cu un dispozitiv standard, toate câmpurile non-statice ale cărora sunt și POD-uri.

Pentru a lucra cu constante de timp de compilare și inițializare statică, C++11 are un concept mai ușor - un tip literal . Și anume:

POD-uri și inițializarea „implicit” și „valoare”

De la C++03, există o diferență între T t; și T t();, precum și între noul T și noul T().

Versiunea cu paranteze goale se numește „inițializarea valorii”, iar fără ele se numește „inițializarea implicită”.

Inițializare implicită: dacă constructorul implicit este banal, atunci nu se face nimic, gunoiul rămâne în obiect. Dacă constructorul implicit nu este banal, atunci este executat.

Inițializare după valoare: dacă există un constructor implicit scris explicit, atunci acesta este executat. Dacă nu (adică dacă constructorul implicit este banal sau este generat automat), atunci obiectul este anulat mai întâi și numai atunci constructorul este executat (dacă nu este trivial). Tipurile scalare sunt setate la zero atunci când sunt inițializate cu o valoare.

Embarcadero Delphi

Toate tipurile sunt considerate structuri de date simple, cu excepția:

Note

  1. GetLastError Arhivat 6 decembrie 2013 la Wayback Machine pe MSDN
  2. Structura STRRET (Windows) . Consultat la 6 aprilie 2013. Arhivat din original pe 18 aprilie 2013.

Vezi și