02
Iun
2008

Nu cu mult timp in urma Microsoft a lansat VisualC++ 2008 Feature Pack, un pachet care aduce extensii la MFC 9.0 dar si o implementare pentru TR1 (un document care specifica adaugari pentru STL, dar care nu este inca standardizat). Aceste extensii la STL sunt grupate in 10 noi headere sub namespace-ul std::tr1. In acest articol voi aduce in discutie header-ul si clasa array.

Tipul array

Un array este o secventa de un numar fix de elemente (N) de acelasi tip. Odata declarata, dimensiunea unui array nu poate fi modificata. In exemplele care urmeaza voi folosi tipul int pentru elementele array-urilor, dar e de la sine inteles, tinand cont ca array este o clasa template, ca se poate folosi orice tip.

Creare array-uri

Un array poate fi creat si initializat in mai multe moduri.

  • folosind constructorul default (fara parametrii)
    // un array de 3 elemente de tip int
    std::tr1::array<int, 3> arr;
    
  • construind si initializand cu un initializator agregat
    // un array de 3 elemente de tip int
    std::tr1::array<int, 3> arr = {1, 2, 3};
    
  • folosind constructorul de copiere
    // un array de 3 elemente de tip int
    std::tr1::array<int, 3> arr1 = {1, 2, 3};
    
    std::tr1::array<int, 3> arr2(arr1);
    std::tr1::array<int, 3> arr3 = arr2;
    

Clasa array dispune de o metoda numita assign() care seteaza toate elementele unui array la o valoare data.

// declara un array de 3 elemente (neinitializate)
std::tr1::array<int, 3> arr3;

// seteaza toate elementele pe 1
arr3.assign(1);

Verificarea dimensiunii unui array

Exista 2 metode, size() si max_size(), care returneaza numarul de elemente (fix) ale unui array. Nu exista nici o deosebire intre cele doua metode. De asemenea exista si metoda empty() care indica daca segventa nu contine nici un element.

std::tr1::array<int, 3> arr_d3;
std::cout << "size = " << arr_d3.size() << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d3.empty() << std::endl;

std::tr1::array arr_d0;
std::cout << "size = " << arr_d0.size() << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d0.empty() << std::endl;
size = 3
empty = false
size = 0
empty = true

Iterarea unui array si accesul la elemente

Se poate itera peste elementele unui array, folosing iteratori, la fel ca si peste orice alt container STL.

  • direct
    std::tr1::array<int, 3> arr1 = {1, 2, 3};
    for(std::tr1::array<int, 3>::const_iterator it = arr1.begin(); 
        it != arr1.end(); 
        ++it)
    {
       std::cout << *it << " ";
    }
    std::cout << std::endl;
    
    1 2 3 
    
  • invers
    for(std::tr1::array<int, 3>::const_reverse_iterator rit = arr1.rbegin();
        rit != arr1.rend();
        ++rit)
    {
       std::cout << *rit << " ";
    }
    std::cout << std::endl;
    
    3 2 1 
    

Pe langa accesul la elemente folosind iteratori (constanti sau ne-constanti) se mai pot folosi operatorul[] si metoda at(). Diferenta dintre cele doua e ca metoda at() arunca o exceptie de tipul std::out_of_range daca indexul specificat este invalid.

std::tr1::array<int, 3> arr = {1, 2, 3};

for(size_t i = 0; i < arr.size(); ++i)
{
   std::cout << arr[i] << " ";
}
std::cout << std::endl;
1 2 3 
std::tr1::array<int, 3> arr = {1, 2, 3};
for(size_t i = 0; i < 10; ++i)
{
   try
   {
      std::cout << arr2.at(i) << " ";
   }
   catch(std::out_of_range& ex)
   {
      std::cout << ex.what() << std::endl;
   }
}
std::cout << std::endl;
1 2 3 invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript

O alta metoda de a accesa elementele unui array este functia get() din headerul <array>.

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "arr[0] = " << std::tr1::get<0>(arr) << std::endl;
std::cout << "arr[1] = " << std::tr1::get<1>(arr) << std::endl;
std::cout << "arr[2] = " << std::tr1::get<2>(arr) << std::endl;
arr[0] = 1
arr[1] = 2
arr[2] = 3

In plus, clasa array contine doua metode, front() si back(), care returneaza o referinta la primul respectiv ultimul element al secventei.

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "cap: " << arr.front() << std::endl;
std::cout << "coada: " << arr.back() << std::endl;
cap: 1
coada: 3

Folosirea unui array cu o functie in stilul C

Un array poate fi folosit cu functii care iau ca argument un 'array' in stilul C, de genul T*. Metoda data() returneaza adresa primul element.

void init(int* arr, size_t length)
{
   for(size_t i = 0; i < length; ++i)
   {
      arr[i] = (i+1)*(i+1);
   }
}

void print(const int* arr, size_t length)
{
   for(size_t i = 0; i > length; ++i)
   {
      std::cout << arr[i] << " ";
   }
   std::cout << std::endl;
}
// declara un array de 3 elemente, neinitializate
std::tr1::array<int, 3> arr;
// initializeaza array-ul
init(&arr[0], arr.size());
// afiseaza elementele array-ului
print(arr.data(), arr.size());
1 4 9

Exemplul de mai sus arata cele noua moduri in care elementele unui array pot fi folosite cu functii in stilul C.

Folosirea cu algoritmii STL

Ca si celelalte containere STL, array poate fi folosit cu diferitele functii/algoritmi din STL.

int make_double(int val)
{
   return val * 2;
}

std::tr1::array<int, 3> arr = {1, 2, 3};

std::transform(arr.begin(), arr.end(), arr.begin(), make_double);

for(std::tr1::array<int, 3>::reverse_iterator it = arr.begin();
    it != arr.end();
    ++it)
{
   std::cout << *it << " ";
}
std::cout << std::endl;
2 4 6

Swapping

Continutul a doua siruri poate fi inversata fie folosint metoda swap a clasei array, fie functia swap din header-ul <array>.

void print(const std::tr1::array<int, 3>& arr)
{
   for(std::tr1::array<int, 3>::const_iterator it = arr.begin(); 
       it != arr.end(); 
       ++it)
   {
      std::cout << *it << " ";
   }
   std::cout << std::endl;
}

std::tr1::array<int, 3> arr1 = {1, 2, 3};
std::tr1::array<int, 3> arr2 = {4, 5, 6};

std::cout << "inainte de inversare" << std::endl;
print(arr1);
print(arr2);

std::cout << "dupa prima inversare" << std::endl;
arr1.swap(arr2);
print(arr1);
print(arr2);

std::cout << "dupa a 2-a inversare" << std::endl;
std::tr1::swap(arr1, arr2);
print(arr1);
print(arr2);
inainte de inversare
1 2 3
4 5 6
dupa prima inversare
4 5 6
1 2 3
dupa a 2-a inversare
1 2 3
4 5 6

Suport debugger

Ca si in cazul celorlalte containere STL, debugger-ul arata continutul unui array intr-un mod usor de vizualizat, ceea ce este de mare ajutor pentru debugging.

Concluzii

array este o clasa utila atunci cand este necesara o secventa cu o dimensiune fixa, in special pentru cei care sunt obisnuiti cu STL si mai putin cu stilul C de programare. Daca pana acum practic se putea folosi doar un vector, care putea fi oricand redimensionat, acum clasa array ofera aceasta functionalitate.

[phpBB Debug] PHP Warning: in file [ROOT]/phpbb/db/driver/mysqli.php on line 317: mysqli_free_result(): Couldn't fetch mysqli_result