31 maja 2013

C++11 - zarządzanie pamięcią pod nowe obiekty w kontenerach sekwencyjnych

W nowym standardzie kontenery sekwencyjne zyskały nowe metody, które lepiej pozwalają nam kontrolować pamięć pod nowo tworzone obiekty. Wykaz wszystkich dostępnych można znaleźć pod adresem:
Wśród nich jest m.in. shrint_to_fit(). W programie poniżej, przedstawiono jego porównanie z już istniejącymi metodami.
  • resize() - zwiększa lub zmniejsza ilość elementów w kontenerze. Jeżeli trzeba dołożyć nowych elementów zostaną one zainicjowane domyślną wartością
  • reserve() - nie tworzy nowych elementów. Jego zadaniem jest zwiększenie miejsca pod nowo tworzone elementy
  • capacity() - podaje ile miejsca zostało przeznaczone na wszystkie elementy
  • shrint_to_fit() - zazwyczaj ilość prealokowanej pamięci jest większa niż liczba elementów w wektorze, za pomocą tej nowej metody możemy zwolnić ekstra pamięć

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void status(const string& func_name, const vector<int>& v) {
    cout << func_name << "size: " << v.size() << ", capacity: " << v.capacity() << endl;
}

int main()
{
    vector<int> v;

    for(int i = 0; i < 3; ++i)
        v.push_back(1);

    status("push_back()     ", v);
    v.resize(5);
    status("resize()        ", v);
    v.shrink_to_fit();
    status("shrint_to_fit() ", v);
    v.reserve(10);
    status("reserve()       ", v);
    v.reserve(3);
    status("reserve()       ", v);

    return 0;
}
Wynik:
push_back()     size: 3, capacity: 4
resize()        size: 5, capacity: 6
shrint_to_fit() size: 5, capacity: 5
reserve()       size: 5, capacity: 10
reserve()       size: 5, capacity: 10
Inny przykład to metoda emplace() (jest też w innych wariantach: emplace_back(), emplace_front()). Jej zadaniem jest stworzenie obiektu w miejscu.
#include <iostream>
#include <vector>

using namespace std;

struct Obj {
    int value;
    Obj(int v) : value(v) {
        cout << "Call constructor, value = " << value << endl;
    }
    Obj(const Obj& o) : value(o.value) {
        cout << "Call copy constructor, value = " << value << endl;
    }
    Obj(const Obj&& o) noexcept : value(std::move(o.value)) {
        cout << "Call move constructor, value = " << value << endl;
    }
    Obj& operator=(const Obj& o) = delete;
};

int main()
{
    vector<Obj> vobj;
    Obj o(111);

    cout << "Testing emplace_back():" << endl;
    vobj.emplace_back(222);

    cout << "Testing push_back():" << endl;
    vobj.push_back(o);

    return 0;
}
Wynik:
Call constructor, value = 111

Testing emplace_back():
Call constructor, value = 222

Testing push_back():
Call copy constructor, value = 111
Call copy constructor, value = 222

Brak komentarzy:

Prześlij komentarz