Diversi modi per aggiungere due vettori in C++ STL

Diversi modi per aggiungere due vettori in C++ STL

In questo articolo, abbiamo esplorato diversi modi per aggiungere due vettori in C++ STL che includono std::copy, insert, concat, overloaded + operator e altre funzioni.

Indice dei contenuti

  1. STL e libreria standard
  2. classe vettoriale
  3. Diversi modi per aggiungere usando la classe vettoriale
    • all'inizio del vettore
    • alla fine del vettore
    • a un indice specifico
  4. Altri modi
    • std::funzione di copia
    • funzione concat definita dall'utente
    • operatori di sovraccarico definiti dall'utente + e +=

1. STL e libreria standard

STL sta da Standard Template Library e come suggerisce il nome è una libreria composta da classi generiche. La sintassi per dichiararne uno è:

template <class local_type_name> class class_name

il che significa che possiamo dichiarare una classe con alcuni membri di tipo generico, ovvero un membro di cui non conosciamo il tipo dall'inizio. Non confondere la prima parola class utilizzato qui per simboleggiare il tipo generico del nome_tipo_locale che verrà utilizzato, con la dichiarazione di una classe.
Può essere utilizzata più di una dichiarazione di tipo generico, come possiamo vedere nel prossimo esempio:

#include<iostream>
using namespace std;

template <class A, class B> class C
{
    public: A a; B b; // generic type members
    C (A x, B y) {a = x; b = y; } // constructor
    void print() {cout << a << "\n" << b; } // function member
};
int main()
{
    C <int, float> obj_name (3, 3.14);
    obj_name.print();

    return 0;
}

La differenza tra le due librerie è che STL funziona con tipi generici mentre la Standard Library funziona con classi di tipi impliciti. Un esempio di classe STL è il vettore class e un esempio di Standard Library potrebbe essere la string classe. Entrambe le classi utilizzano quasi lo stesso comportamento, l'unica differenza consiste nei tipi che manipolano.

2. classe vettoriale

Abbiamo visto in precedenza come viene definita una classe generica. Ora vediamo qual è la definizione del vettore

template < class T, class Alloc = allocator<T> > class vector;

Quindi, fondamentalmente un vettore ha una T tipo generico con alias come tipo di membro vector::value_type e un Alloc tipo con alias come tipo di membro vector::allocator_type.

Informazioni su T abbiamo visto prima quali forme possono assumere, un tipo implicito o definito.

E l'alloc?

Questo è il tipo di oggetto allocatore utilizzato per definire il modello di allocazione dello storage. Per impostazione predefinita, l'allocatore viene utilizzato il modello di classe, che definisce il modello di allocazione della memoria più semplice ed è indipendente dal valore.

Per utilizzare oggetti vettoriali dobbiamo includere il file di intestazione del vettore.

#include <vector>

Alcuni esempi di dichiarazioni:

vector<int> first;
vector<int> second (4,100);                       // four ints with value 100
vector<int> third (second.begin(),second.end());  // iterating through second
vector<int> fourth (third);                       // a copy of third

Notare l'uso di un solo argomento nel tipo generico, il tipo Alloc è inizializzato per impostazione predefinita.

Il costruttore dell'iteratore può anche essere usato per costruire da array come nell'esempio successivo:

int v[3] = {1,2,3};
vector<int> fifth ( &*v , &*v+3 );

Si noti l'indirizzamento di v, che inizia dal puntatore ve termina alla fine di esso;

Poiché &e * sono funzioni complementari, l'affermazione precedente potrebbe essere semplicemente scritta:

int v[3] = {1,2,3};
vector<int> fifth ( v , v+3 );

e se non conoscessimo la dimensione di v

int v[] = {1,2,3};
vector<int> fifth ( v , v + sizeof(v) / sizeof(int) );

Per iterare tutti gli elementi del vettore quinto possiamo usare l'iteratore classe come mostrato nell'istruzione successiva:

vector<int>::iterator i;

for ( i = fifth.begin(); i != fifth.end(); i++ )
    cout<< *i <<" ";

Il codice completo è come incolto

    #include <iostream>
    #include <vector>
    using namespace std;

    int main()
    {
        vector<int> first;
        vector<int> second (4,100);                       
        vector<int> third (second.begin(),second.end());  
        vector<int> fourth (third);                       

        int v[] = {1,2,3};

        vector<int> fifth ( v , v + sizeof(v) / sizeof(int) );

        vector<int>::iterator i;

        for ( i = fifth.begin(); i != fifth.end(); i++ )
            cout<< *i <<" ";

        return 0;
    }

3. Diversi modi per aggiungere

Una volta definiti alcuni vettori, la prossima cosa che possiamo fare è manipolarne gli elementi. Un modo è aggiungere il metodo che potrebbe essere in diversi casi:

  • all'inizio del vettore

possiamo usare la funzione di inserimento per inserire all'inizio del quinto vettore il avanti vettore, e per questo dobbiamo specificarne la dimensione completa

    vector<int>::iterator i;
    i = fifth.begin();
    fifth.insert( i, fourth.begin(), fourth.end() );
  • alla fine del vettore

abbiamo due metodi qui, uno è usare solo l'esempio precedente, invece di inizializzare i con l'inizio del quinto lo inizializzeremo alla fine

    vector<int>::iterator i;
    i = fifth.end();
    fifth.insert( i, fourth.begin(), fourth.end() );

e il secondo è usando il push_back funzione elemento per elemento

    vector<int>::iterator i;
    for ( i = fourth.begin(); i != fourth.end() ; i++ ) 
        fifth.push_back ( *i );
  • a un indice specificato

possiamo usare lo stesso approccio dell'inserimento iniziale solo che dobbiamo sommare con il numero di elementi dopo di che vorremo fare l'accodamento e aggiungere una condizione per verificare se io è fuori portata.

    vector<int>::iterator i;
    i = fifth.begin() + 2;
    if ( *i != NULL )
        fifth.insert( i, fourth.begin(), fourth.end() );

4. Altri modi

  • funzione di copia

La definizione della funzione di copia è:

    template <class InputIterator, class OutputIterator>
      OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);

e il prossimo esempio eseguirà una copia del quarto elementi sopra il quinto vettore:

    copy(fourth.begin() , fourth.end() , back_inserter(fifth) );

Qui abbiamo usato back_inserer funzione che crea un iteratore back-insert che inserisce nuovi elementi alla fine di x. Un iteratore di inserimento a ritroso è un tipo speciale di iteratore di output progettato per consentire agli algoritmi che di solito sovrascrivono gli elementi di inserire invece nuovi elementi automaticamente alla fine del contenitore.

  • funzione concat definita dall'utente

    Possiamo definire la nostra funzione per implementare una concatenazione di 2 vettori ma è obbligatorio includere il vettore e algoritmo intestazioni
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    template<typename T> void concat( vector<T>& a, vector<T>& b)
        {
         for_each( b.begin(), b.end(), [&](int value){ a.push_back(value); } );
        }

la prossima chiamata aggiungerà gli elementi del quarto vettore alla fine del quinto vettore

    concat( fifth, fourth);
  • operatori di overload definiti dall'utente + e +=

Il modo più interessante per scrivere codice in C++ è sovraccaricare gli operatori di base.
In questo caso possiamo ripensare agli operatori + e +=per concatenare due vettori.
L'operatore + necessita di un vettore aggiuntivo per memorizzare le informazioni mentre l'operatore +=aggiungerà elementi al primo.

implementazione per + operatore

    template <typename T> vector<T> operator + ( vector<T>& a, vector<T>& b) 
        {
        vector <T> c = a;
        c.insert(c.end(), b.begin(), b.end() );
        return c;  
        }
    fifth = fifth + fourth;

implementazione per +=operatore

    template <typename T> vector<T>& operator += ( vector<T>& a, vector<T>& b) 
        {
        a.insert(a.end(), b.begin(), b.end() );
        return a;
        }
    fifth += fourth;

Un suggerimento utile
Un aumento generale delle prestazioni per concatenare è controllare la dimensione dei vettori e aggiungere quello che ha gli elementi più piccoli a quello più grande.

    if(fourth.size() > fifth.size()) {
        fourth.insert(fourth.end(), fifth.begin(),fifth.end());
    } else {
        fifth.insert(fifth.end(), fourth.begin(),fourth.end());
    }

No