0

Ich arbeite an einer Lib, die Art von wissenschaftlichen Berechnungen durchführen wird. Es ist beabsichtigt, mit GUIs verwendet werden und daher die Berechnungen asynchron durchgeführt werden und die GUI (oder was auch immer Warteschlange eine Aufgabe in die lib) erhalten einen Rückruf auf einem zuvor angegebenen std::function. Diese Rückrufe werden immer einen kleinen Statusantwortobjekt erhalten, nämlichVerwenden von Rvalue-Referenzen für asynchronen Rückruf

struct StatusResponse { 
    StatusResponse(int respC, std::string respS): responseCode(respC), 
    responseString(std::move(respS)) {}; 
    int responseCode; 
    std::string responseString; 
}; 

Diese Rückrufe sind Feuer und vergessen, sie nichts zurück (void) und es besteht keine Notwendigkeit für eine weitere Aktion zu warten, ausgeführt durch der Rückruf Daher sind auch die StatusResponse-Objekte temporär. Es scheint, als gäbe es jetzt mehrere Möglichkeiten. Meine erste Idee, die Callback-Funktion wurde definiert, als

template<typename T0> 
using Action = std::function<void(std::shared_ptr<T0>)>; 

es Aufruf folgt wie

rdt::Action<rdt::StatusResponse> callback; 

std::shared_ptr<rdt::StatusResponse> response = 
std::make_shared<rdt::StatusResponse> 
(rdt::errorcode::DEVICE_ID_OUT_OF_RANGE, std::string {"Device ID out 
of Range!"}); 

callback(response); 
return; 

Dies scheint ziemlich ineffizient und teuer (Verwendung von std::shared_ptr für fire-and-forget, außerdem muss das Programm Rückkehr in der Library-Funktion, nur um wieder zurück ...) Nun kochte ich einen alternativen Weg nach oben:

void callback(std::unique_ptr<StatusResponse> response); 

std::unique_ptr<StatusResponse> response = 
std::make_unique<StatusResponse>(0, "success!"); 

callback(std::move(response)); 

Dies scheint jedoch immer noch ineffektiv zu sein, weil ich eine Hülle um ein Objekt baue, das sowieso zerstört wird.

void callback(StatusResponse&& response); 

StatusResponse response {0, "Success!"}; 
callback(std::move(response)); 

ist möglich oder sogar

callback(StatusResponse {0, "Success!"}); 

So, jetzt bin ich ziemlich unsicher über diese Möglichkeiten.

Erste Frage: Ist die std::move in der Struktur geeignet?

Zweite Frage: Welche Lösung bietet den besten Geschwindigkeitsvorteil? Der Rückruf wird wahrscheinlich wie

genannt werden
std::thread t(callback, StatusResponse {0, "Success!"}); 
t.detach(); 

Ich begann das Lernen über rvalue Verweise und intelligente Zeiger nur so ist jede Hilfe sehr dankbar!

EDIT: Ich führte einen Test und SergeyA scheint richtig zu sein. Die rvalue Referenz Art und Weise erzeugt die folgende Debugging-Ausgabe:

Constructor Called! 
Copy Constructor Called! 
Copy Constructor Called! 
Destructor Called! 
Destructor Called! 
Callback called! 
Called callback! 
Exiting caller! 
Exiting callback! 
Destructor Called! 

einen Umzug Konstruktor Bereitstellung führt zu Copy Constructor Called durch Move Constructor Called ersetzt

Antwort

0

Nein, rvalue Referenz nicht in Ordnung ist - vorübergehend gelöscht werden würde, nachdem die Anweisung abgeschlossen ist . In der Tat ist der effizienteste Weg, nach Wert zu kopieren, aber verwenden Sie einen Move-Konstruktor in Ihrer Struktur und erstellen Sie ihn aus dem temporären oder std::move() Ergebnis.

+0

Danke für Ihre Antwort. Könnten Sie präzisieren, was Sie genau vorschlagen? Ich kämpfe um zu verstehen, was du wirklich meinst. – java4ever

Verwandte Themen