2012-02-14 22 views

Respuesta

108

La diferencia es que con std::pair debe especificar los tipos de ambos elementos, mientras que std::make_pair creará un par con el tipo de elementos que se le pasan, sin necesidad de contarlo. Eso es lo que pude reunir de varios documentos de todos modos.

Ver este ejemplo de http://www.cplusplus.com/reference/std/utility/make_pair/

pair <int,int> one; 
pair <int,int> two; 

one = make_pair (10,20); 
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char> 

Aparte del bono conversión implícita de que, si no se ha utilizado make_pair que tendría que hacer

one = pair<int,int>(10,20) 

cada vez que se asigna a uno, que sería molesto con el tiempo ...

+0

En realidad, los tipos deben deducirse en tiempo de compilación sin la necesidad de especificar. – Chad

+0

@Tor Sí, sé cómo usarlos a ambos, solo tenía curiosidad si había una razón para 'std :: make_pair'. Aparentemente es solo por conveniencia. –

+0

@Jay Parece que sí. –

23

No hay diferencia entre usar make_pair y llamar explícitamente al pair constructor con argumentos de tipos especificados. std::make_pair es más conveniente cuando los tipos son detallados porque un método de plantilla tiene una deducción de tipo basada en sus parámetros dados. Por ejemplo,

std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair; 
std::vector<int> emptyV; 

// shorter 
vecOfPair.push_back(std::make_pair(emptyV, emptyV)); 

// longer 
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV)); 
18

Vale la pena señalar que este es un lenguaje de programación común en la plantilla de C++. Se lo conoce como la expresión idiomática Object Generator, puede encontrar más información y un buen ejemplo here.

Editar Como alguien sugirió en los comentarios (ya que se eliminó) lo siguiente es un extracto ligeramente modificado del enlace en caso de que se rompa.

Un Generador de objetos permite la creación de objetos sin especificar explícitamente sus tipos. Se basa en una propiedad útil de las plantillas de funciones que las plantillas de clase no tienen: los parámetros de tipo de una plantilla de función se deducen automáticamente de sus parámetros reales. std::make_pair es un ejemplo simple que devuelve una instancia de la plantilla std::pair según los parámetros reales de la función std::make_pair.

template <class T, class U> 
std::pair <T, U> 
make_pair(T t, U u) 
{ 
    return std::pair <T, U> (t,u); 
} 
+0

Creo que faltan referencias en el código '&' –

+0

@duck En realidad '&&' desde C++ 11. – Justme0

4

make_pair crea una copia extra sobre el constructor directo. Siempre escribo mis pares para proporcionar una sintaxis simple.
Esto muestra la diferencia (por ejemplo Rampal Chaudhary):

class Sample 
{ 
    static int _noOfObjects; 

    int _objectNo; 
public: 
    Sample() : 
     _objectNo(_noOfObjects++) 
    { 
     std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl; 
    } 

    Sample(const Sample& sample) : 
    _objectNo(_noOfObjects++) 
    { 
     std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl; 
    } 

    ~Sample() 
    { 
     std::cout<<"Destroying object "<<_objectNo<<std::endl; 
    } 
}; 
int Sample::_noOfObjects = 0; 


int main(int argc, char* argv[]) 
{ 
    Sample sample; 
    std::map<int,Sample> map; 

    map.insert(std::make_pair(1, sample)); 
    //map.insert(std::pair<int,Sample>(1, sample)); 
    return 0; 
} 
+3

Estoy bastante seguro de que la copia adicional se eliminará en todos los casos, si la configuración de optimización del compilador es lo suficientemente alta. –

+0

¿Por qué querrías confiar en la optimización del compilador? – sjbx

+0

Obtengo los mismos resultados con ambas versiones, y con 'std :: move' justo dentro de' insert' y/o alrededor de lo que sería una referencia a 'sample'. Es solo cuando cambio 'std :: map ' a 'std :: map ' que reduzco el número de objetos construidos, y solo cuando elimino el constructor de copia elimino todas las copias (obviamente) Después de realizar ambos cambios, mi resultado incluye una llamada al constructor predeterminado y dos llamadas al destructor para el mismo objeto. Creo que me estoy perdiendo algo. (g ++ 5.4.1, C++ 11) –

23

Como @MSalters respondieron anteriormente, ahora se puede utilizar llaves para hacer esto en C++ 11 (solo se verifica esto con un C++ 11 compilador):

pair<int, int> p = {1, 2}; 
6

argumentos de plantilla de clase no podía deducirse desde el constructor antes de C++ 17

antes de C++ 17 no se podía escribir algo como:

std::pair p(1, 'a'); 

ya que inferiría los tipos de plantilla del constructor.

C++ 17 hace posible la sintaxis y, por lo tanto, make_pair redundante.

Consulte también:

Antes de C++ 17, std::make_pair nos permitió escribir código menos detallado:

auto p = std::make_pair(1, 'a'); 

en lugar de la más detallado:

std::pair<int,char> p{1, 'a'}; 

que repite los tipos, y puede ser muy largo.

La inferencia de tipo funciona en ese caso anterior a C++ 17 porque make_pair no es un constructor.

make_pair es esencialmente equivalente a:

template<class T1, class T2> 
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) { 
    return std::pair<T1, T2>(t1, t2); 
} 

El mismo concepto se aplica a:

  • inserter vs insert_iterator
Cuestiones relacionadas