Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[STL] Metodyka dodawania obiektów do kontenerów

Ostatnio zmodyfikowano 2013-04-05 16:05
Autor Wiadomość
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.
P-79924
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:
C/C++
lista.push_back( std::move( Ala() );
Możesz też użyć metod
emplace_back()
 i
emplace_front()
.
C/C++
#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ę ;)
P-79925
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 :)
P-79930
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.
P-79932
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.
P-79938
RazzorFlame
» 2013-04-05 14:53:46
C/C++
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.
P-79978
pekfos
» 2013-04-05 15:04:44
...
My tu mówimy o C++11, a nie C++ (C++03).
P-79984
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++.
P-79992
« 1 » 2
  Strona 1 z 2 Następna strona