c++ - ejemplo - ¿Cuál es el propósito de std:: make_pair vs el constructor de std:: pair?
struct pair c++ (6)
¿Cuál es el propósito de std::make_pair
?
¿Por qué no simplemente hacer std::pair<int, char>(0, ''a'')
?
¿Hay alguna diferencia entre los dos métodos?
Como @MSalters respondió anteriormente, ahora puede usar llaves para hacer esto en C ++ 11 (solo verificado esto con un compilador de C ++ 11):
pair<int, int> p = {1, 2};
La diferencia es que con std::pair
necesita 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>
Además del bono de conversión implícito, si no usaste make_pair tendrías que hacer
one = pair<int,int>(10,20)
cada vez que se asigna a uno, lo que sería molesto con el tiempo ...
No hay diferencia entre usar make_pair
y llamar explícitamente al constructor de pair
con argumentos de tipo 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 esta es una expresión común en la programación de plantillas de C ++. Se lo conoce como el modismo del generador de objetos, 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 Object Generator 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
dependiendo de 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);
}
make_pair crea una copia extra sobre el constructor directo. Siempre escribo mis pares para proporcionar una sintaxis simple.
Esto muestra la diferencia (ejemplo de 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;
}
Los argumentos de la plantilla de clase no pudieron inferirse del constructor antes de C ++ 17
Antes de C ++ 17 no podías escribir algo como:
std::pair p(1, ''a'');
ya que eso inferiría tipos de plantilla de los argumentos del constructor.
C ++ 17 hace posible esa sintaxis y, por make_pair
tanto, make_pair
redundant.
Antes de C ++ 17, std::make_pair
nos permitía escribir código menos detallado:
MyLongClassName1 o1();
MyLongClassName2 o2();
auto p = std::make_pair(o1, o2);
en lugar de lo más detallado:
std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};
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 insert_iterator
vs insert_iterator
.
Ver también: