[STL] Metodyka dodawania obiektów do kontenerów
Ostatnio zmodyfikowano 2013-04-05 16:05
akwes Temat założony przez niniejszego użytkownika |
[STL] Metodyka dodawania obiektów do kontenerów » 2013-04-04 15:42:16 Witam :) Pisałem sobie prosty program kiedy naszła mnie ciekawość względem pewnego zagadnienia. Mamy sobie listę: std::list < Ala > Lista; . Dodajemy obiekt Lista.push_back( Ala() ); . Co się teraz stało? Został użyty konstruktor domyślny, a następnie konstruktor kopiujący i później destruktor (idący w parze do pierwszego obiektu, który był automatyczny). Jeżeli obiekt Ala był duży, to używanie konstruktora kopiującego nie jest miłe ani fajne. Należy jeszcze dodać, że obiekty na liście będą się zwalniać automatycznie. Zmieniamy listę na: std::list < Ala *> Lista; i dodajemy obiekt w ten sposób Lista.push_back( new Ala() ); . Teraz nie używamy już konstruktora kopiującego, jednak używamy wolniejszego new oraz musimy pamiętać aby sami zwolnić dany zasób. Czy jest jakaś metoda, aby trzymać na liście obiekty a nie wskaźniki do obiektów, jednocześnie nie korzystając z konstruktora kopiującego? //Edit, @pekfos, fixnąłem temat :) //Edit2, Wybaczcie zamknięcie tematu, ale zaczyna się offtop :) Rozwiązanie zostało podane. |
|
pekfos |
» 2013-04-04 15:46:55 Implementacja kontenerów STL w C++11 używa przeniesienia, zamiast kopiowania (gdzie to możliwe, oczywiście). Jak zdefiniujesz konstruktor przenoszący, to możesz zoptymalizować dodawanie nowych obiektów. Dodajesz wtedy tak: lista.push_back( std::move( Ala() );
Możesz też użyć metod emplace_back() i emplace_front() . #include <iostream> #include <list> #include <utility>
class Test { public: Test() { std::cout << "Konstruktor" << std::endl; } Test( const Test & ) { std::cout << "Konstruktor kopiujacy" << std::endl; } Test( Test && ) { std::cout << "Konstruktor przenoszacy" << std::endl; } ~Test() { std::cout << "Destruktor" << std::endl; } };
int main() { { std::cout << "-----------------------------------------\npush_back(Test())" << std::endl; std::list < Test > l; for( int a = 0; a < 5; ++a ) l.push_back( Test() ); } { std::cout << "-----------------------------------------\npush_back(std::move(Test()))" << std::endl; std::list < Test > l; for( int a = 0; a < 5; ++a ) l.push_back( std::move( Test() ) ); } { std::cout << "-----------------------------------------\nemplace_back()" << std::endl; std::list < Test > l; for( int a = 0; a < 5; ++a ) l.emplace_back(); } }
PS: w nazwie tematu masz vector, a w treści listę ;) |
|
akwes Temat założony przez niniejszego użytkownika |
» 2013-04-04 16:05:38 Czyli taka możliwość występuje dopiero od C++11? Eh, no nic, to z tym featurem będę musiał poczekać aż w Marmalade dodadzą obsługę C++11 :) |
|
Monika90 |
» 2013-04-04 16:32:49 lista.push_back( std::move( Ala() ); |
move jest tutaj zbędne, bo wyrażenie Ala() to r-wartość. Zatem wystarczy, tak: lista.push_back( Ala() ); i konstruktor przenoszący zostanie użyty jeżeli istnieje. |
|
Elaine |
» 2013-04-04 17:38:19 Najlepsze byłoby lista.emplace_back(); . Marmalade używa starego GCC (4.4.1), ale chyba nie aż tak starego, żeby to nie działało, wariadyki i r-referencje są przecież od 4.3. |
|
RazzorFlame |
» 2013-04-05 14:53:46 Test( Test && ) { std::cout << "Konstruktor przenoszacy" << std::endl; }
|
Łatafak? Podwójna referencja czy to literówka czy zamierzony efekt bo tego raczej nie czaje. Operator AND chyba nie jest używany w tym sposobie. |
|
pekfos |
» 2013-04-05 15:04:44 ... My tu mówimy o C++11, a nie C++ (C++03). |
|
Elaine |
» 2013-04-05 15:51:09 My tu mówimy o C++11, a nie C++ (C++03). |
Od dwóch lat C++11 to jest C++. |
|
« 1 » 2 |