Domanda

Cosa è std::pair perché dovrei usarlo e quali vantaggi apporta boost::compressed_pair Portare?

È stato utile?

Soluzione

std::pair è un tipo di dati per raggruppare due valori insieme come un singolo oggetto. std::map lo usa per coppie chiave-valore.

Mentre stai imparando pair, potresti controllare tuple.È come pair ma per raggruppare un numero arbitrario di valori. tuple fa parte di TR1 e molti compilatori lo includono già nelle loro implementazioni della Libreria Standard.

Inoltre, controlla il capitolo 1, "Tuple", del libro Le estensioni della libreria standard C++:Un tutorial e un riferimento di Pete Becker, ISBN-13:9780321412997, per una spiegazione approfondita.

alt text

Altri suggerimenti

compressed_pair utilizza alcuni trucchi del modello per risparmiare spazio.In C++, un oggetto (o minuscola) non può avere lo stesso indirizzo di un oggetto diverso.

Quindi, anche se lo hai

struct A { };

Ala dimensione non sarà 0, perché in tal caso:

A a1;
A a2;
&a1 == &a2;

sarebbe valido, il che non è consentito.

Ma molti compilatori eseguiranno quella che viene chiamata "ottimizzazione della classe base vuota":

struct A { };
struct B { int x; };
struct C : public A { int x; };

Ecco, va bene per B E C avere la stessa dimensione, anche se sizeof(A) non può essere zero.

COSÌ boost::compressed_pair trae vantaggio da questa ottimizzazione e, ove possibile, erediterà dall'uno o dall'altro dei tipi della coppia se è vuota.

Quindi a std::pair potrebbe assomigliare a (ho eliso molto, ctors ecc.):

template<typename FirstType, typename SecondType>
struct pair {
   FirstType first;
   SecondType second;
};

Ciò significa che se uno dei due FirstType O SecondType È A, tuo pair<A, int> deve essere più grande di sizeof(int).

Ma se usi compressed_pair, il codice generato sarà simile a:

 struct compressed_pair<A,int> : private A {
    int second_;
    A first() { return *this; }
    int second() { return second_; }
 };

E compressed_pair<A,int> sarà grande solo quanto sizeof(int).

A volte è necessario restituire 2 valori da una funzione e spesso è eccessivo creare una classe solo per quello.

std:pair torna utile in questi casi.

Penso che boost:compressed_pair sia in grado di ottimizzare i membri di dimensione 0.Che è utile soprattutto per i macchinari con modelli pesanti nelle biblioteche.

Se controlli direttamente i tipi, è irrilevante.

Può sembrare strano sentire che compress_pair si preoccupa di un paio di byte.Ma in realtà può essere importante se si considera dove è possibile utilizzare compress_pair.Consideriamo ad esempio questo codice:

boost::function<void(int)> f(boost::bind(&f, _1));

Può improvvisamente avere un grande impatto utilizzare compress_pair in casi come quelli sopra.Cosa potrebbe succedere se boost::bind memorizza il puntatore a funzione e il segnaposto _1 come membri in sé o in a std::pair in se stesso?Beh, potrebbe gonfiarsi fino a sizeof(&f) + sizeof(_1).Supponendo che un puntatore a funzione abbia 8 byte (non raro soprattutto per le funzioni membro) e il segnaposto abbia un byte (vedi la risposta di Logan per il motivo), allora avremmo potuto aver bisogno di 9 byte per l'oggetto bind.A causa dell'allineamento, questo potrebbe gonfiarsi fino a 12 byte su un normale sistema a 32 bit.

boost::function incoraggia le sue implementazioni ad applicare un'ottimizzazione di piccoli oggetti.Ciò significa che per piccolo funtori, un piccolo buffer incorporato direttamente nel file boost::function l'oggetto viene utilizzato per memorizzare il funtore.Per i funtori più grandi, l'heap dovrebbe essere utilizzato utilizzando l'operatore new per ottenere memoria.Intorno alla spinta versione 1.34, si è deciso di adottarlo questa ottimizzazione, perché si pensava che si potessero ottenere grandi vantaggi in termini di prestazioni.

Ora, un limite ragionevole (ma forse ancora piuttosto piccolo) per un buffer così piccolo sarebbe 8 byte.Cioè, il nostro oggetto bind piuttosto semplice lo farebbe non adattarsi al piccolo buffer e richiederebbe la memorizzazione dell'operatore new.Se l'oggetto bind sopra utilizzasse a compressed_pair, può effettivamente ridurre le sue dimensioni a 8 byte (o spesso a 4 byte per puntatori a funzione non membri), perché il segnaposto non è altro che un oggetto vuoto.

Quindi, quello che potrebbe sembrare uno spreco di pensieri per pochi byte, in realtà può avere un impatto significativo sulle prestazioni.

È una classe standard per memorizzare una coppia di valori.Viene restituito/utilizzato da alcune funzioni standard, come std::map::insert.

boost::compressed_pair afferma di essere più efficiente: Vedere qui

std::pair è utile per un paio di altre classi contenitore nell'STL.

Per esempio:

std::map<>
std::multimap<> 

Entrambi memorizzano std::coppie di chiavi e valori.

Quando si utilizzano la mappa e la multimappa, spesso si accede agli elementi utilizzando un puntatore a una coppia.

Informazioni addizionali:boost::compressed_pair è utile quando uno dei tipi della coppia è una struttura vuota.Questo viene spesso utilizzato nella metaprogrammazione dei modelli quando i tipi della coppia vengono dedotti a livello di codice da altri tipi.Alla fine, di solito hai una qualche forma di "struttura vuota".

Preferirei std::pair per qualsiasi utilizzo "normale", a meno che non ti interessi di metaprogrammazione di modelli pesanti.

Non è altro che una struttura con due variabili sotto il cofano.

In realtà non mi piace usare std::pair per i ritorni di funzioni.Il lettore del codice dovrebbe sapere cos'è .first e cos'è .second.

Il compromesso che utilizzo a volte è creare immediatamente riferimenti costanti a .first e .second, nominando chiaramente i riferimenti.

A cosa serve std::pair, perché dovrei usarlo?

È altrettanto semplice una tupla di due elementi.È stato definito nella prima versione di STL in tempi in cui i compilatori non supportavano ampiamente modelli e tecniche di metaprogrammazione che sarebbero necessarie per implementare tipi più sofisticati di tuple come Boost.Tuple.

È utile in molte situazioni. std::pair viene utilizzato nei contenitori associativi standard.Può essere utilizzato come una semplice forma di intervallo std::pair<iterator, iterator> - quindi si possono definire algoritmi che accettano un singolo oggetto che rappresenta l'intervallo invece di due iteratori separatamente.(È un'alternativa utile in molte situazioni.)

A volte ci sono due informazioni che passi sempre insieme, sia come parametro, sia come valore di ritorno, o altro.Certo, potresti scrivere il tuo oggetto, ma se sono solo due piccole primitive o simili, a volte una coppia sembra andare bene.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top