Lebzeit von Objekten



  • Hallo zusammen,

    mir ist bekannt, dass Objekte innerhalb ihres Scopes {} gültig sind.
    Jetzt stellt sich mir die Frage, wielange zurückgegebene Objekte gültig sind.

    Ich dachte dabei an etwas wie:

    fb(bar() << create_foo());
    

    Also folgendes Beispiel liefert mir bei gcc 4.7.1:

    #include <iostream>
    
    struct foo{
    	~foo(){
    		std::cout << "delete foo" << std::endl;
    	}
    };
    
    struct bar{
    	bar& operator<<(const foo&){
    		std::cout << "bar" << std::endl;
    		return *this;
    	}
    };
    
    struct foobar{
    	void operator()(const bar&){
    		std::cout << "foobar" << std::endl;
    	}
    };
    
    foo create_foo(){
    	return foo();
    };
    
    int main(){
    	foobar fb;
    	fb(bar() << create_foo());
    }
    

    bar
    foobar
    delete foo

    Die Frage ist für mich nun, ob der Standard diese Lebensdauer auch garantiert.
    Also meine Vermutung ist, dass der Scope mit dem abschließenden Semikolon beendet wird.
    Liege ich damit richtig?
    Also generell möchte ich etwas machen wie:

    mysql_connection(select("mytable") << equals("my_column1", "value") << greater("my_column2", 2));
    

    wobei ich dann die conditions in einem std::vector zwischenspeicherns möchte.
    Also equals und greater liefern Objekte zurück, die von condition abgeleitet sind.

    Gruß,
    XSpille



  • XSpille schrieb:

    Also meine Vermutung ist, dass der Scope mit dem abschließenden Semikolon beendet wird.

    Vermute ich auch, aber wieso interessiert das überhaupt? Du bindest jedes temporäre Objekt an const-ref. Damit ist doch schon sicher, dass das Objekt hinter der Referenz gültig ist. Sehe da keine Probleme.



  • Temporäre Objekte leben solange bis der Ausdruck vollständig ausgewertet wurde. Dann verschwinden sie. Der Ausdruck

    XSpille schrieb:

    fb(bar() << create_foo());
    

    erzeugt zwei temporäre Ojekte. Eins vom Typ bar und eins vom Typ foo. Wenn die Funktion foobar::operator() "fertig" ist, werden diese Objekte zerstört. Quasi beim Semikolon.



  • out schrieb:

    XSpille schrieb:

    Also meine Vermutung ist, dass der Scope mit dem abschließenden Semikolon beendet wird.

    Vermute ich auch, aber wieso interessiert das überhaupt? Du bindest jedes temporäre Objekt an const-ref. Damit ist doch schon sicher, dass das Objekt hinter der Referenz gültig ist. Sehe da keine Probleme.

    Damit wäre aber nur sichergestellt, dass foo lebt bis der operator<< ausgeführt ist, oder?

    DANKE krümelkacker!



  • XSpille schrieb:

    out schrieb:

    XSpille schrieb:

    Also meine Vermutung ist, dass der Scope mit dem abschließenden Semikolon beendet wird.

    Vermute ich auch, aber wieso interessiert das überhaupt? Du bindest jedes temporäre Objekt an const-ref. Damit ist doch schon sicher, dass das Objekt hinter der Referenz gültig ist. Sehe da keine Probleme.

    Wenn operator<< abgearbeitet ist, brauchst du foo doch auch nicht mehr, es hat seinen Zweck doch dann schon erfüllt.



  • out schrieb:

    XSpille schrieb:

    out schrieb:

    XSpille schrieb:

    Also meine Vermutung ist, dass der Scope mit dem abschließenden Semikolon beendet wird.

    Vermute ich auch, aber wieso interessiert das überhaupt? Du bindest jedes temporäre Objekt an const-ref. Damit ist doch schon sicher, dass das Objekt hinter der Referenz gültig ist. Sehe da keine Probleme.

    Wenn operator<< abgearbeitet ist, brauchst du foo doch auch nicht mehr, es hat seinen Zweck doch dann schon erfüllt.

    Wie gesagt, ich möchte foo in einem vector speichern (und nicht sofort in einen String umwandeln), folglich schon 😉



  • XSpille schrieb:

    Wie gesagt, ich möchte foo in einem vector speichern (und nicht sofort in einen String umwandeln), folglich schon 😉

    Wenn der op<< das foo im vector speichert, dann wird das Speichern ja durchgeführt, bevor der op<< zu Ende ist und damit auch, bevor das temporäre foo zerstört wird.



  • hi XSpille

    mysql_connection(select("mytable") << equals("my_column1", "value") << greater("my_column2", 2));
    

    wofuer brauchst man sowas ?

    ich denk mir mal das mit dem vector der mysql-string gebaut wird, aber warum der aufwand ?

    Meep Meep



  • pumuckl schrieb:

    XSpille schrieb:

    Wie gesagt, ich möchte foo in einem vector speichern (und nicht sofort in einen String umwandeln), folglich schon 😉

    Wenn der op<< das foo im vector speichert, dann wird das Speichern ja durchgeführt, bevor der op<< zu Ende ist und damit auch, bevor das temporäre foo zerstört wird.

    Nein... Ich speichere nur einen Zeiger auf das foo-Objekt und benötige es später beim fb()-Aufruf wieder.

    Meep Meep schrieb:

    mysql_connection(select("mytable") << equals("my_column1", "value") << greater("my_column2", 2));
    

    wofuer brauchst man sowas ?

    Also ich baue mir etwas wie:

    template<>
    struct DBTable<Foo>{
    
    	typedef ColumnInfo<int_getter<Foo>, int_setter<Foo> > bar_type;
    	typedef ColumnInfo<string_getter<Foo>, string_setter<Foo> > foo_type;
    	typedef PrimaryKey<Foo, const bar_type&, const foo_type&> primary_key_type;
    	typedef ForeignKey<Foo, const getter<Foo, FooBar>&, const setter<Foo, FooBar>&> foreign_key_type;
    
    	static const bar_type bar;
    	static const foo_type foo;
    	static const primary_key_type primary_key;
    	static const foreign_key_type foreign_key;
    	static const std::string table;
    };
    
    const DBTable<Foo>::bar_type DBTable<Foo>::bar("bar", &Foo::bar, &Foo::bar);
    const DBTable<Foo>::foo_type DBTable<Foo>::foo("foo", &Foo::foo, &Foo::foo);
    const DBTable<Foo>::primary_key_type DBTable<Foo>::primary_key(DBTable<Foo>::bar, DBTable<Foo>::foo);
    const DBTable<Foo>::foreign_key_type DBTable<Foo>::foreign_key(DBTable<Foo>::foobar, DBTable<Foo>::foobar);
    const std::string DBTable<Foo>::table("foo");
    

    Ich will dann später etwas machen wie:

    entity_manager(select<Foo>() << where(DBTable<Foo>::foreign_key, foobar));
    

    wobei der foreign_key sich dann auf den primary_key von FooBar bezieht.

    Ob man intern direkt nen String zusammen baut, ober erst, wenn er benötigt wird ist wohl Geschmacksache.


Log in to reply