¿Cuál es el propósito de std::make_pair
?¿Cuál es el propósito de std :: make_pair frente al constructor de std :: pair?
¿Por qué no acaba de hacer std::pair<int, char>(0, 'a')
?
¿Hay alguna diferencia entre los dos métodos?
¿Cuál es el propósito de std::make_pair
?¿Cuál es el propósito de std :: make_pair frente al constructor de std :: pair?
¿Por qué no acaba de hacer std::pair<int, char>(0, 'a')
?
¿Hay alguna diferencia entre los dos métodos?
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 ...
En realidad, los tipos deben deducirse en tiempo de compilación sin la necesidad de especificar. – Chad
@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. –
@Jay Parece que sí. –
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));
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);
}
Creo que faltan referencias en el código '&' –
@duck En realidad '&&' desde C++ 11. – Justme0
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;
}
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. –
¿Por qué querrías confiar en la optimización del compilador? – sjbx
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
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};
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
En C++ 11, se puede hacer casi en su totalidad y sin make_pair . Ver [mi respuesta] (http://stackoverflow.com/a/21995963/2288585). – PlagueHammer