Shared Pointer als unbenannter Parameter



  • Hallo zusammen,

    Ich würde gerne einen Shared Pointer an eine Funktion als unbenannter Parameter übergeben um ein Objekt während der Ausführung der Funktion am Leben zu erhalten. Jetzt kam mir die Befürchtung, dass Compiler eventuell diesen Parameter wegoptimieren könnten, da klar ist, dass dieser nicht innerhalb der Funktion verwendet wird. Ist die Befürchtung begründet oder wird vom Standard garantiert, dass immer eine Kopie des Parameter auf den Stack gelegt wird?



  • Die Frage ist, wieso?

    Entweder braucht deine Funktion diesen Parameter (oder eben Daten auf die der Parameter verweist), oder halt nicht.

    Wenn du sagst, die Daten sollen solange leben, wie die Funktion lang ist, dann riecht das nach Nebenläufigkeit und da wirds ganz schnell sehr komplex.

    Erklär mal mehr was du vorhast.


  • Mod

    Der Compiler darf die Seiteneffekte (um die es dir geht) nicht wegoptimieren.

    In diesem Fall sind diese Seiteneffekte das Zerstören des gemanagten Objektes im Destruktor des Smart-Pointers und das Inkrementieren/Dekrementieren des Ref-Counters.

    Edit: Ich frage mich nur gerade, das muss doch nicht die Funktion selbst verantworten, das kann doch auch der Aufrufer, in dem er einfach einen Smart-Pointer im selben Scope wie der Funktionsaufruf deklariert? Wozu da die Funktion verkomplizieren?



  • Skym0sh0 schrieb:

    Erklär mal mehr was du vorhast.

    Die Funktion soll von einem Job asynchron ausgeführt werden und wird im dazu als std::function mit std::bind übergeben. Der Job selber hängt an einem Shared Pointer. Der Job muss garantiert mindestens so lange leben bis die Funktion ausgeführt wurde aber auch nicht länger, falls nicht nötig.



  • Arcoth schrieb:

    Der Compiler darf die Seiteneffekte (um die es dir geht) nicht wegoptimieren.

    Compiler optimieren doch ständig Kopien (z.B RVO) weg? Woher weiß der denn immer, dass die Kopien keine Seiteneffekte haben die ich gerne hätte?



  • Indem er sicht die Konstruktoren und Destruktoren anschaut, natürlich. Aber das was du da machen willst klingt generell erst mal nach Schwachsinn. Kannst du das mal in einem kleinen Codebeispiel demonstrieren? (pref < 120 Zeilen)



  • cooky451 schrieb:

    Aber das was du da machen willst klingt generell erst mal nach Schwachsinn. Kannst du das mal in einem kleinen Codebeispiel demonstrieren? (pref < 120 Zeilen)

    Ich denke das wird schwierig. Ich denke ich habe schon recht erschöpfend erklärt was ich selber machen möchte. Das Jobinterface und die Implementierung ist nicht vom mir und darf ich hier auch nicht veröffentlichen.

    Was ich machen möchte sieht in etwa so aus:

    shared_ptr<job_t> myJob = make_Job("MyJob");
    myJob->append_async_call(bind(myfunc,myjob));
    


  • Ja, die Lebenszeit ist da garantiert, schwachsinnig sieht das allerdings immer noch aus.



  • Wirklich gefallen tut mir das auch so nicht, aber ich denke mit dem Job-Interface geht es nicht wirklich besser.


  • Mod

    TNA schrieb:

    Compiler optimieren doch ständig Kopien (z.B RVO) weg?

    Das ist eine Ausnahme. Du solltest auf jeden Fall folgenden Absatz kennen:

    12.8/31 schrieb:

    When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization123.
    This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

    • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
    • in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object
    • when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
    • when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy/move operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration.

    123) Because only one object is destroyed instead of two, and one copy/move constructor is not executed, there is still one object destroyed for each one constructed.

    Ersteres davon ist NRVO - das Dritte wird dann bei (N)RVO auch noch angewendet.



  • Arcoth schrieb:

    12.8/31 schrieb:

    When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization123.

    Folgt aus dem letzten Satz nicht, dass es in diesem konkreten Fall egal ist, ob die Kopie wegoptimiert wird? Die Zerstörung findet zu dem Zeitpunkt statt, an dem das letzte der beiden Objekte (Kopie und Original) zerstört würde, also lebt der Smart-Pointer auf jeden Fall solange, wie er soll.

    (Ich kann mir die RVO-Regeln nämlich nicht merken.)


  • Mod

    Bashar schrieb:

    Folgt aus dem letzten Satz nicht, dass es in diesem konkreten Fall egal ist, ob die Kopie wegoptimiert wird?

    Es ging nie um copy-elision, sondern darum, dass der ganze Parameter wegoptimiert wird, was natürlich nie erlaubt ist (außer vielleicht, wenn er ein Aggregat ist und nicht verwendet wird o.ä.).

    Aber du hast Recht, das macht hier keinen Unterschied.



  • Arcoth schrieb:

    Bashar schrieb:

    Folgt aus dem letzten Satz nicht, dass es in diesem konkreten Fall egal ist, ob die Kopie wegoptimiert wird?

    Es ging nie um copy-elision

    Compiler optimieren doch ständig Kopien (z.B RVO) weg?

    Hab ich aus deinem Posting rauskopiert.


  • Mod

    Korrigiere: Es ging dem TE nie darum, das möglicherweise irgendeine Temporary elidiert wird, sondern es ging darum, ob der Parameter überhaupt existiert. Ob eine Temporary elidiert wird, ist, wie du ja sehen hast, vollkommen irrelevant, da irgendein shared_ptr -Objekt in der Funktion existieren muss.



  • Das Zitat ist vom TE.


  • Mod

    Bashar schrieb:

    Das Zitat ist vom TE.

    Weiß ich. Ich habe darauf offensichtlich auch geantwortet.

    Aber copy elision ist für sein Problem unwichtig. Denn das weg-optimieren von Kopien oder Parametern sind zwei völlig verschiedene Dinge, von denen für ihn nur letzteres zählt.



  • Das Wegoptimieren von Kopien ist die einzige Optimierung, die das beobachtbare Verhalten ändern darf. Wenn es darum nie ging, ging es um nichts.


  • Mod

    Bashar schrieb:

    Das Wegoptimieren von Kopien ist die einzige Optimierung, die das beobachtbare Verhalten ändern darf. Wenn es darum nie ging, ging es um nichts.

    Gut erkannt.


Anmelden zum Antworten