temporäre instanz bei default argument vermeiden
-
ich möchte gern folgendes machen:
void foo(boost::any const & arg = 0) { ... }ich gehe davon aus, dass dieser code für jeden "leeren" aufruf eine temporäre instanz von boost::any erzeugt.
also hab ich es geändert:
static boost::any const none; void foo(boost::any const & arg = none) { ... }so muss doch keine temporäre instanz mehr erzeugt werden?
was wäre in folgendem fall:static boost::any const none; void foo(boost::any const & arg = none) { ... } // andere compileunit class my_class { public: my_class() { foo(); } // ruft foo ohne argument auf }; my_class my_object; // globale instanz von my_classsehe ich das richtig, dass dieser code undefiniertes verhalten erzeugt, weil foo aufgerufen wird, bevor none sicher erzeugt wurde?
-
suma dartson schrieb:
sehe ich das richtig, dass dieser code undefiniertes verhalten erzeugt, weil foo aufgerufen wird, bevor none sicher erzeugt wurde?
Das hängt davon ab, was foo mit dem Argument anstellt. Ein lvalue kann an eine Referenz gebunden werden, sofern es auf entsprechend reservierten Speicher verweist - es ist nicht zwingend erforderlich, dass das Objekt bereits oder noch lebt.
-
Würde sich bei deinem Beispiel nicht Überladung anbieten?
void foo(); void foo(boost::any const& arg);Damit wird bestimmt keine unnötige Kopie erzeugt oder undefiniertes Verhalten ausgelöst. Ausserdem entfällt eine Abfrage wie if (arg == none), du ja weisst, ob ein Argument übergeben wurde.
Gruß
Don06
-
camper schrieb:
Das hängt davon ab, was foo mit dem Argument anstellt.
mindestens mal
if(!arg.empty()) { ... }Don06 schrieb:
Würde sich bei deinem Beispiel nicht Überladung anbieten?
wenn es nur um die eine stelle ginge, ja. aber es geht um ein interface, wo foo öfter mal überschrieben wird, da möchte ich das lieber mit einer funktion und default-argument machen.
-
suma dartson schrieb:
camper schrieb:
Das hängt davon ab, was foo mit dem Argument anstellt.
mindestens mal
if(!arg.empty()) { ... }könnte auch
if(&arg!=&none&&!arg.empty()) { ... }sein, dann besteht kein Problem (nicht, dass ich das für eine gute Lösung halte).
-
Mach es so:
void foo(boost::any const & arg = boost::any()) { ... }Dann wird zwar auch immer ein temporäres Objekt erzeugt, allerdings ist ein "leeres any" sehr billig zu erzeugen & löschen.
Ein "any" mit einem Integer drin kostet dagegen u.U. wesentlich mehr.Ich weiss nicht ob die aktuelle Boost Version eine Art "small object optimization" bei any verwendet. Wenn das so wäre wäre ein "any" mit einem Integer drinnen vermutlich auch nicht SEHR teuer. Wenn es keine Optimierung gibt ist der Unterschied allerdings sicher dramatisch.
-
hustbaer schrieb:
Mach es so:
void foo(boost::any const & arg = boost::any()) { ... }ok, das scheint mir ein guter kompromiss zu sein. ein leeres any kostet wirklich nicht viel.