2017-11-01 1 views
2

in dem folgenden Code, ich möchte die use_count() des shared_ptr in die std::async bewegt 1 sein:use_count() von shared_ptr zog in ein std :: async in gcc 4.6.3

#include <memory> 
#include <iostream> 
#include <future> 

using namespace std; 

void fun(shared_ptr<int> sp) 
{ 
    cout << "fun: sp.use_count() == " << sp.use_count() << 
     " (in gcc 4.6.3, is there a way to make this 1?)\n"; 
} 

int main() 
{ 
    auto sp1 = make_shared<int>(5); 

    auto fut = async(
     launch::async, 
     fun, 
     move(sp1) 
    ); 
} 

Meine Plattform nutzt gcc 4.6.3 und der Code oben gibt diese Ausgabe (fun: sp.use_count() == 2):

fun: sp.use_count() == 2 (in gcc 4.6.3, is there a way to make this 1?) 

Auf coliru.stacked-crooked.com, erhalte ich das Verhalten, das ich will (fun: sp.use_count() == 1):

fun: sp.use_count() == 1 (in gcc 4.6.3, is there a way to make this 1?) 

Ich bin nicht sicher, was Compiler coliru verwendet, aber ich vermute, es ist neuer als gcc 4.6.3.

Gibt es eine Möglichkeit, um das gewünschte Verhalten zu erhalten, ohne meinen Compiler von gcc 4.6.3 zu aktualisieren?

+5

GCC 4.6 ist mittlerweile sehr alt, und seine Unterstützung für C++ 11 fehlt ziemlich. Wenn du kannst, solltest du upgraden. –

+0

Wenn ich raten müsste, würde ich sagen, dass die Zählung 2 ist, weil Ihr Compiler keine Kopie für das 'sp' Argument zu' fun' macht. Was ist, wenn Sie 'sp1' nicht explizit, sondern nur temporär im async-Aufruf konstruieren? – Darhuuk

+0

hier eine Schätzung, aber was passiert, wenn Sie den Parameterwert stattdessen als R-Wert-Referenz ('&&') ändern? – Default

Antwort

0

Obwohl std::async kopiert alle Argumente, beim Aufruf der Funktion es perfekt-leitet die Argumente auf die aufrufbar, so dass die Argument Wert Kategorie beibehalten wird.

Die Argumente für std::async sind nur MoveConstructible sein erforderlich, sonst wäre es nicht möglich sein, std::unique_ptr in std::async passieren.

Mit anderen Worten, das richtige Verhalten ist sp.use_count() == 1 und das ist, was ich mit einem alten g ++ - 5.3.1 beobachte.


Überprüfen Sie, ob der folgende Code mit dem Compiler kompiliert, wo Sie sp.use_count() == 2 beachten:

using namespace std; 

void fun(unique_ptr<int> p) { 
    cout << "fun " << *p << '\n'; 
} 

int main() { 
    unique_ptr<int> sp(new int{1}); 

    auto fut = async(
     launch::async, 
     fun, 
     move(sp) 
    ); 

    fut.get(); 
} 
+0

Das kompiliert nicht auf meiner Plattform (ARM gcc 4.6.3). Es kann online auf Wandbox gesehen werden. Wandbox hat kein gcc 4.6.3, aber es hat gcc 4.6.4, und es kompiliert auch nicht auf dieser Version: ([link] (https://wandbox.org/permlink/hpUJIRPSyrePHLqo)). Allerdings kompiliert es auf gcc 4.7.3: ([link] (https://wandbox.org/permlink/EiTlxiGvrreWk4tj)) Ich versuche zu vermeiden, meinen Compiler zu aktualisieren, aber wenn ich dieses Verhalten will, ist es Ich werde mehr und mehr danach suchen, was ich tun muss ... – Quokka

1

eine mögliche Abhilfe

void fun(shared_ptr<int>* sp) 
{ 
    unique_ptr<shared_ptr<int>> guard(sp); 

    cout << "fun: sp.use_count() == " << sp->use_count() << 
     " (in gcc 4.6.3, is there a way to make this 1?)\n"; 
} 

int main() 
{ 
    auto sp1 = make_shared<int>(5); 

    auto fut = async(
     launch::async, 
     fun, 
     new shared_ptr<int>(move(sp1)) 
    ); 
} 

sein könnte, was gesagt, wäre es interessant, zu sehen, wo gcc463 erstellt die zusätzliche Kopie im Originalcode; Es sieht so aus, als würde das temporäre Element, das in async() von "dease_copy" übergeben wird, nicht wie ein rvalue an den Parameter "fun()" weitergeleitet werden. Können Sie nicht mit Ihrem Debugger eingreifen, um zu sehen, was vor sich geht?

Verwandte Themen