2016-05-24 6 views
1

Wie geht man mit konstanten (oder nicht konstanten) Referenzen innerhalb von STL-Containern vor und bearbeitet sie. Sagen wir, ich habe eine Funktion:Übergabe von reference_wrapper-Objekten als Funktionsargumente in C++ 11

bool foo(const Obj& A, const Obj& B) { 
    // do some computation on A & B 
} 

und da A & B immer zusammen auftreten, würde Ich mag sie in einem STL Paar setzen:

bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
} 

jetzt jedoch beide Objekte Eine & B und in der sie kopiert ein Paar jedes Mal, wenn foo gerufen werden muss. Als ich mich umsah, fand ich reference_wrapper in C++ 11. Obwohl etwas zu tun, wie dies funktioniert nicht ganz:

bool foo(const std::pair<std::reference_wrapper<Obj>, std::reference_wrapper<Obj>>& A_and_B) { 
    // do some computation on A & B 
} 

bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    foo(std::make_pair(std::ref(A_and_B.first), std::ref(A_and_B.second))); 
} 

Was ist der richtige Weg der Weitergabe Behälter mit Referenzwerten ohne Zeiger verwendet werden?

+0

Es gibt keine "die" richtige Art und Weise, aber für Sie eine Option ist das formale Argument Typ 'Paar const &', oder einfach nur 'Paar const' zu machen. –

Antwort

-1

Da Sie das Paar als Referenz übergeben, wird es nicht kopiert. Obj A=A_and_B.first erstellt jedoch eine Kopie. Wenn Sie das vermeiden möchten, können Sie eine Referenz auf das Element erhalten, d. H.

Obj &A=A_and_B.first.

+0

Mir macht der Downvote nichts aus, aber ich bin neugierig, was ich in meiner Antwort falsch gemacht habe ..? – nikaza

+0

Ich bin nicht der Downvoter, aber möglicherweise, weil "Obj my_A = A_and_B.first" nicht (jetzt) ​​im OP-Code vorhanden ist? –

+0

@ Cheers und hth. - Alf Heh, schöner Punkt, es behebt, danke :) – nikaza

1

Um zu vermeiden, kopieren, wenn make_pair, warum definieren Sie nicht das Paar als std::pair<Obj&, Obj&> direkt?

#include <iostream> 
#include <string> 
#include <functional> 
class Obj 
{ 
}; 

bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
    std::cout << __func__ << std::endl; 
} 

bool foo(const std::pair<Obj&, Obj&>& A_and_B) { 
    // do some computation on A & B 
    std::cout << "ref version foo" << std::endl; 
} 

int main(void) 
{ 
    Obj A; 
    Obj B; 
    foo(std::make_pair(std::ref(A), std::ref(B))); 
    return 0; 
} 
+0

Sie würden wollen die erste Überlastung entfernen und die Verweise zu ändern, um 'const' in den zweiten zu verweisen. –

0

Da std::make_pair unterstützt bewegen Semantik, Sie müssen nur Ihre Funktion schreiben, wie Sie vorgeschlagen, aber beim Aufruf es Objekte A und B in die std::make_pair bewegen, wie unten dargestellt:

// Just as you already suggested 
bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
} 

Anruf es als:

int main(void) 
{ 
    Obj A; // work on A 
    Obj B; // work on B 
    auto A_and_B = std::make_pair(std::move(A), std::move(B)); // effectively moves A and B; no copies! 
    // A and B are now reset, but you can use A_and_B.first and A_and_B.second! 
    foo(A_and_B ); 
    return 0; 
} 

Live demo.

+0

Es scheint * sehr * unwahrscheinlich, dass das OP die Argumentobjekte verschieben will. –

+0

@ Cheersandhth.-Alf Es scheint, jeder ist verwirrt und die Verwendung von 'Reference_wrapper' ist ein guter Beweis dafür. Ich glaube, die OP will 'A' und 'B' zusammen binden, ohne unnötige Kopien. –

+0

Ich stimme mit diesem Kommentar, Modulo s/jeder/alle anderen/g.Aber das Bewegen ist nicht die Antwort, weil das Bewegen (1) für bewegliche Typen die tatsächlichen Argumente ändert, was unerwünscht ist, und (2) für nicht bewegbare Typen zum Kopieren reduziert wird, was ebenfalls im Allgemeinen unerwünscht ist. Das Übergeben eines Referenzpaares macht die Arbeit gut. ;-) –

1

Hier ist ein Weg, vorbei an nur ein Paar von Referenzen (kein Kopieren):

#include <utility>   // pair 
#include <functional>  // ref 
#include <iostream> 
using namespace std; 

struct Obj {}; 

auto foo(pair<Obj const&, Obj const&> const ab) 
{ 
    Obj const& a = ab.first; 
    Obj const& b = ab.second; 
    cout << &a << " " << &b << endl; 
} 

auto main() -> int 
{ 
    Obj a; 
    Obj b; 
    cout << &a << " " << &b << endl; 
    foo(make_pair(ref(a), ref(b))); 
} 

Dies funktioniert gut, weil std::make_pair für std::reference_wrapper Argumente besondere Unterstützung hat, dann Bezug auf den genannten herzuleiten einzugeben.

std::reference_wrapper ist der Ergebnistyp von std::ref.

+0

Ich mag das, ich denke es ist der sauberste Vorschlag. – nikaza