¿Cuál es el propósito de std:: make pair vs el constructor de std:: pair?


¿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?

6 answers

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 los elementos que se le pasan, sin necesidad de decirlo. Eso es lo que podría deducir de varios documentos de todos modos.

Vea 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 de la bonificación de conversión implícita de la misma, si no utilizas make_pair tendrías que hacer

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

Cada tiempo asignado a uno, lo cual sería molesto con el tiempo...

 122
Author: Tor Valamo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-14 01:51:34

Como @MSalters respondió anteriormente, ahora puede usar llaves para hacer esto en C++11 (solo lo verificó con un compilador de C++11):

pair<int, int> p = {1, 2};
 26
Author: PlagueHammer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-22 21:06:30

No hay diferencia entre usar make_pair y llamar explícitamente al constructor 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 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));
 23
Author: devil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-14 01:49:24

Vale la pena señalar que este es un lenguaje común en la programación de plantillas de C++. Se conoce como el modismo del Generador de objetos, puedes encontrar más información y un buen ejemplo aquí.

Edit Como alguien sugirió en los comentarios (desde 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 la función plantillas que no tienen las plantillas de clase: 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);
}
 19
Author: mkm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-03 09:37:19

Los argumentos de la plantilla de clase no se pueden inferir del constructor antes de C++17

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

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

Puesto que eso inferiría tipos de plantilla de los argumentos del constructor.

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

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 la más detallada:

std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};

Que repite los tipos, y puede ser muy largo.

La inferencia de tipos funciona en ese caso pre-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.

Véase también:

 10
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-22 15:03:57

Make_pair crea una copia extra sobre el constructor directo. Siempre he escrito 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;
}
 4
Author: EmpZoooli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-28 14:34:19