2017-05-15 3 views
0

fand ich zufällig dieses Problem auf C++, hatte aber total keine Ahnung, wie es passiert war, nutzen Sie bitte Code-Schnipsel überprüfen:Der Mechanismus der shared_ptr

int main() { 
     int *aptr = new int(20); //Declare an integer space with 20, and aptr points to it 
     shared_ptr<int> a(aptr); //Declare a shared_ptr to points where aptr points 

     stringstream ss; 
     ss << a; 
     const char *chstr = ss.str().c_str(); // Save the address as string 

     void *address; 
     sscanf(chstr, "%p", (void **)&address); // Convert string back to pointer 

     a = NULL; // Free the shared pointer 
     cout << *reinterpret_cast<int*>(address) << endl; // Output: 0, 20 has gone 

     return 0; 
} 

Gibt es jemand könnte mir sagen, warum die Adresse gewesen befreit ?
Ich habe den ursprünglichen Ganzzahlzeiger "aptr" nicht manipuliert, aber irgendwie ist der Platz verschwunden, wegen des shared_ptr?
Ich würde gerne wissen, wie es passiert ist, danke euch allen!

+2

Gut. Du schießt in dein Bein und fragst dann "warum ist etwas falsch passiert"? Erstens: Sie speichern die Adresse der temporären Zeichenfolge, das ist wirklich schlecht.Zweitens: Sie weisen NULL shared_ptr zu, anstatt Reset aufzurufen. – ForEveR

+0

Ich weiß nicht, was Sie erreichen wollen oder wirklich, was Sie fragen. Ich denke, Sie müssen den Unterschied zwischen Zeigern und den Dingen, auf die sie hinweisen, besser verstehen. –

+0

.... a = NULL; nullpointer –

Antwort

7

Der ganze Zweck hinter std::shared_ptr ist, das dynamisch zugewiesene Objekt zu übernehmen. Sobald std::shared_ptr das Eigentum an einem dynamisch zugewiesenen Objekt übernimmt, entweder über std::make_shared oder indem Sie ihm direkt einen Zeiger zuweisen, besitzt std::shared_ptr es, sperren Sie Lager und Lauf. Der Besitz bedeutet automatisch delete das dynamisch begrenzte Objekt, wenn der letzte Verweis auf das Objekt mit dynamischem Bereich den Gültigkeitsbereich verlässt. Das ist, was die shared_ptr ist, und nichts anderes.

a = NULL; 

verwendet, um dieses shared_ptr ‚s Zuweisungsoperator die shared_ptr -ige Zeiger (*) zu ersetzen. Da das ursprüngliche Objekt mit dynamischem Bereich, das shared_ptr besitzt, keine andere Referenz hat, ist shared_ptrdelete der ursprüngliche Zeiger, der verwendet wurde, um es zu erstellen.

Die Tatsache, dass Sie immer noch den ursprünglichen, nativen Zeiger auf die int haben, ist irrelevant. shared_ptr ist es egal. Die ganze Sache bekommt delete d.

Wenn Sie nicht shared_ptr wollen delete was auch immer Sie new ed, und verwenden Sie einen nativen Zeiger für entweder nicht verwenden shared_ptr, oder stellen Sie sicher, ein immer noch rund ist, solange Sie noch einen nativen Zeiger verwenden müssen zu dem zugrunde liegenden Objekt.

(*) Dies erstellt implizit eine andere shared_ptr und verwendet den regulären Zuweisungsoperator.

+0

Vielen Dank, es hilft mir sehr, sehr detailliert, sehr klar. –

+0

Ein anderer Gedanke, den ich fragen möchte, ist, findet dies auch in Android :: sp (starker Zeiger) statt? –

1

Dieser Code kompiliert nicht in g ++ 4.2.1 (aber als Sam erwähnt, erfüllt es mit Version 6):

Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp 
main.cpp:17:11: error: no viable overloaded '=' 
     a = NULL; // Free the shared pointer 
     ~^~~~~ 

By the way, sollten Sie shared_ptr::reset verwenden:

In In allen anderen Fällen erwirbt shared_ptr den Besitz von p mit einer Verwendung count von 1 und optional mit del und/oder alloc als deleter und allocator.

Zusätzlich wird ein Aufruf dieser Funktion die gleichen Nebenwirkungen hat, als ob Shared_ptr Destruktor aufgerufen wurde, bevor sein Wert geändert (einschließlich die Streichung des verwalteten Objekts, wenn diese Shared_ptr einzigartig war).


Auch string::c_str überprüfen. Sie speichern die Adresse einer temporären Zeichenfolge, was der Beginn von etwas schlechtem ist.

+0

Kompiliert mit gcc 6.3.1 –

+0

Danke @SamVarshavchik, und nette Antwort! – gsamaras

Verwandte Themen