webentwicklung-frage-antwort-db.com.de

Was ist der Zweck von std :: make_pair gegenüber dem Konstruktor von std :: pair?

Was ist der Zweck von std::make_pair?

Warum nicht einfach std::pair<int, char>(0, 'a')?

Gibt es einen Unterschied zwischen den beiden Methoden?

162
user542687

Der Unterschied ist, dass mit std::pair Sie müssen die Typen beider Elemente angeben, während std::make_pair erstellt ein Paar mit dem Typ der Elemente, die an es übergeben werden, ohne dass Sie es mitteilen müssen. Das ist es, was ich sowieso aus verschiedenen Dokumenten sammeln konnte.

Siehe dieses Beispiel aus 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>

Abgesehen von dem impliziten Conversion-Bonus müssten Sie dies tun, wenn Sie make_pair nicht verwenden würden

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

jedes Mal, wenn Sie eine zugewiesen haben, was im Laufe der Zeit ärgerlich wäre ...

147
Tor Valamo

Wie @MSalters oben geantwortet hat, können Sie dies jetzt in C++ 11 mit geschweiften Klammern tun (dies wurde gerade mit einem C++ 11-Compiler überprüft):

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

Es gibt keinen Unterschied zwischen der Verwendung von make_pair und den Konstruktor pair mit den angegebenen Typargumenten explizit aufrufen. std::make_pair ist praktischer, wenn die Typen ausführlich sind, da bei einer Vorlagenmethode die Typableitung auf den angegebenen Parametern basiert. Beispielsweise,

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));
25
devil

Es ist erwähnenswert, dass dies eine gebräuchliche Redewendung in der C++ - Vorlagenprogrammierung ist. Es ist als Objektgenerator-Idiom bekannt. Weitere Informationen und ein gutes Beispiel finden Sie hier .

Bearbeiten Wie jemand in den Kommentaren vorgeschlagen hat (seitdem entfernt), ist das Folgende ein leicht modifizierter Auszug aus dem Link, falls er kaputt geht.

Ein Objektgenerator ermöglicht die Erstellung von Objekten, ohne deren Typ explizit anzugeben. Es basiert auf einer nützlichen Eigenschaft von Funktionsschablonen, die Klassenschablonen nicht haben: Die Typparameter einer Funktionsschablone werden automatisch aus ihren tatsächlichen Parametern abgeleitet. std::make_pair Ist ein einfaches Beispiel, das eine Instanz der Vorlage std::pair Abhängig von den tatsächlichen Parametern der Funktion std::make_pair Zurückgibt.

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

Klassenvorlagenargumente konnten vor C++ 17 nicht aus dem Konstruktor abgeleitet werden

Vor C++ 17 konnte man so etwas nicht schreiben:

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

da dies Vorlagentypen aus den Konstruktorargumenten ableiten würde.

C++ 17 macht diese Syntax möglich, und daher make_pair redundant.

Vor C++ 17 wurde std::make_pair erlaubte uns, weniger ausführlichen Code zu schreiben:

MyLongClassName1 o1();
MyLongClassName2 o2();
auto p = std::make_pair(o1, o2);

statt der ausführlicheren:

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

das wiederholt die Typen und kann sehr lang sein.

Typinferenz funktioniert in diesem Fall vor C++ 17, weil make_pair ist kein Konstruktor.

make_pair entspricht im Wesentlichen:

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

Das gleiche Konzept gilt für inserter vs insert_iterator.

Siehe auch:

Minimales Beispiel

Um die Dinge konkreter zu machen, können wir das Problem minimal beobachten mit:

main.cpp

template <class MyType>
struct MyClass {
    MyType i;
    MyClass(MyType i) : i(i) {}
};

template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
    return MyClass<MyType>(i);
}

int main() {
    MyClass<int> my_class(1);
}

dann:

g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp

kompiliert gerne, aber:

g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp

scheitert mit:

main.cpp: In function ‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’
     MyClass my_class(1);
             ^~~~~~~~

und erfordert stattdessen zu arbeiten:

MyClass<int> my_class(1);

oder der Helfer:

auto my_class = make_my_class(1);

die eine reguläre Funktion anstelle eines Konstruktors verwendet.

Getestet mit GCC 8.1.0, Ubuntu 16.04 .

make_pair erstellt eine zusätzliche Kopie über den direkten Konstruktor. Ich habe meine Paare immer eingegeben, um eine einfache Syntax zu gewährleisten.
Dies zeigt den Unterschied (Beispiel von 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
EmpZoooli

verwenden Sie ab c ++ 11 nur die einheitliche Initialisierung für Paare. Also statt:

std::make_pair(1, 2);

oder

std::pair<int, int>(1, 2);

benutz einfach

{1, 2};
1
Mahmoud Badri