Eine Sprache = Nur ein mittel zum Zweck



  • für Resourcen-kritische Mittel- und Großprojekte ist C++ nach wie vor mit die erste Wahl.



  • Senfkohl schrieb:

    C++ ist nichts halbes und nichts ganzes. Wie schon gesagt, kann man natürlich mit C++ genauso systemnahmen Code schreiben wie mit C. Aber wenn man dies tut, nutzt man lediglich die Sprachfeatures von C++, die es aus C übernommen hat, ergo kann man auch gleich bei C bleiben.

    Nein. Man benutzt Klassen und Templates und und und.

    Beispiel von voriger Woche:
    Für ein wenig mathematiklastiges Zeugs möchte ich sehr schnell Quadratzahlen generieren.
    Kleines Meßprogramm, um zu sehen, ob JedesmalQuadrieren oder UngeradeZahlenAufsummieren besser ist.

    #include <iostream>
    #include <ctime>
    
    using namespace std;
    
    class SquareGenerator{
    	private:
    	int value_;
    	int step_;
    	public:
    	SquareGenerator(){
    		value_=1;
    		step_=1;
    	}
    	inline void step(){
    		step_+=2;
    		value_+=step_;
    	}
    	int value(){
    		return value_;
    	}
    };
    
    int main()
    {
    	int sum=0;
    	clock_t start=clock();
    	for(int o=0;o<1000000;++o){
    #if 1
    		for(int i=1;i<10000;++i)
    			sum+=i*i;
    #else
    		for(SquareGenerator s;s.value()<100000000;s.step())
    			sum+=s.value();
    #endif
    	}
    	cout<<clock()-start<<'\n';
    	cout<<sum<<'\n';
        return 0;
    }
    

    macht mit #if 1

    L6:
    	movl	$1, %edx
    	.p2align 2,,3
    L7:
    	movl	%edx, %eax
    	imull	%edx, %eax
    	addl	%eax, %ebx
    	incl	%edx
    	cmpl	$10000, %edx
    	jne	L7
    	incl	%ecx
    	cmpl	$1000000, %ecx
    	jne	L6
    

    Der Code sieht überzeugend aus.

    Aber macht mit #if 0

    L6:
    	movl	$1, %eax
    	movl	$3, %edx
    	.p2align 2,,3
    L7:
    	addl	%eax, %ebx
    	addl	%edx, %eax
    	addl	$2, %edx
    	cmpl	$99999999, %eax
    	jle	L7
    	incl	%ecx
    	cmpl	$1000000, %ecx
    	jne	L6
    

    Kann man da auch nur im gerinsgten sehen, daß

    for(SquareGenerator s;s.value()<100000000;s.step())
    			sum+=s.value();
    

    statt entsprechendem C-Code verwendet wurde, der mir aufgewürdet hätte, die Quadratzahlenlogik mit der sie benutzenden Logik zu vermischen? Nein. Alles sauber und hundertprozentig wegoptimiert.
    C++ erlaubt es, daß man viel weiter abstrahiert, als es in C möglich ist, und doch kommt der gleiche Code raus. Mit C++ muß man keine Zusatzkosten für Abstraktion zahlen.



  • also ich persönlich mag C ja lieber als c++, denn es ist eine kompakte sprache.



  • hustbaer schrieb:

    Irgendwie finde ich die Argumentation "schlechter weil mehr Features" etwas komisch. Die liesse sich genauso auf LINQ oder andere neue C# Features anwenden. Aber jeder liebt LINQ. Wieso liebt dann nicht jeder den neuen C++ Standard

    vielleicht liegts daran, dass LINQ ein an sich separates element ist, das zwar in die .NET-sprache(n) integriert, aber einen ganz bestimmten, fest umrissenen zweck erfüllen soll (ähnlich embedded-SQL in anderen sprachen). z.b. .NET-anwendungen, die nix mit datenbanken machen, werden davon nicht berührt. dem gegenüber erscheinen die neuerungen des C++ standards als wildes, unausgegorenes durcheinander. teilweise wurde versucht, mängel zu beseitigen, andererseits wurde an vielen ecken neues drangeflickt, wovon heute noch niemand ahnen kann, welche konsequenzen das mal haben wird. wahrscheinlich wird's zu 'ner radikalen änderung führen, wie in zukunft in C++ programmiert wird.
    🙂



  • +fricky schrieb:

    vielleicht liegts daran, dass LINQ ein an sich separates element ist, das zwar in die .NET-sprache(n) integriert, aber einen ganz bestimmten, fest umrissenen zweck erfüllen soll (ähnlich embedded-SQL in anderen sprachen). z.b. .NET-anwendungen, die nix mit datenbanken machen, werden davon nicht berührt.

    so ähnlich wäre mein idealbild der c++-anwendungen. was man nicht braucht, verwendet man einfach nicht.

    +fricky schrieb:

    wahrscheinlich wird's zu 'ner radikalen änderung führen, wie in zukunft in C++ programmiert wird.
    🙂

    ich denke, die neuerungen im c++-standard sind alle berechtigt und sehr sehr toll. nur krankt c++ an forderung, zu allen älteren standard und sogar zu c kompatibel sein zu wollen.
    ohne den ballast sollte man mal versuchen, eine sprache zu bauen, die konsequent das zero-abstraction-overhead-prinzip durchzieht (macht c++ nämlich nicht) und noch dazu einfach ist (ist c++ nämlich nicht).
    egal, wie es ausgeht, der neue c++-standard wird mit sicherheit ganz enorme auswirkungen auf die anderen großen sprachen und zukünftige sprachen haben. es wird außerdem wie damals bei den templates wohl zehn jahr dauern, bis man die ganzen möglichkeiten entdeckt, die drin stecken.
    manche sachen wie die rvalue referenzen schreien danach, eine neue sprache zu bauen, die das kann, aber nicht so gefrickelt ist. initializer lists, die ihre größe nicht zur compilezeit kennen, das ist doch zum heulen!, aber die syntax ist der richtige weg.



  • volkard schrieb:

    +fricky schrieb:

    vielleicht liegts daran, dass LINQ ein an sich separates element ist, das zwar in die .NET-sprache(n) integriert, aber einen ganz bestimmten, fest umrissenen zweck erfüllen soll (ähnlich embedded-SQL in anderen sprachen). z.b. .NET-anwendungen, die nix mit datenbanken machen, werden davon nicht berührt.

    so ähnlich wäre mein idealbild der c++-anwendungen. was man nicht braucht, verwendet man einfach nicht.

    naja, bei z.b. sowas LINQ wirste aber nur vor die wahl gestellt, wenn du's mit datenbanken zu tun kriegst. und die ist einfach nur: benutze ich's, oder mach' ich aus irgendwelchen gründen eine konventionelle lösung. aber in C++ gibts selbst für kleinkram viele verschiedene möglichkeiten, das gleiche zu tun und jede hat ihre ganz eigenen sonderbaren nebeneffekte. das macht C++ sogar im kleinen schon sperrig und schwer benutzbar.

    volkard schrieb:

    aber die syntax ist der richtige weg.

    ...vielleicht. wenn man chinesisch mag.
    🙂



  • +fricky schrieb:

    volkard schrieb:

    aber die syntax ist der richtige weg.

    ...vielleicht. wenn man chinesisch mag.
    🙂

    Naja, beim von mir genannten, ist es ok, würde ich sagen.
    Vector<int> v(5); lege ein Array an mit 5 Elementen.
    Vector<int> v{5}; lege ein Array an mit nur einem Element, nämlich 5.
    Die Idee ist gut und damit lassen sich etliche seltsame Schnittstellen dahingehend vereinfachen, daß man nicht mehr ins Handbuch gucken muß, auch in Basic und vielen anderen Sprachen.

    Aber klar gibt es auch Seiten, die man wirklich nur dulden kann in der Annahme, daß die Kompatibilität zu bestehendem Code die oberste Maxime ist:

    Explicit conversion operators
    Standard C++ added the explicit keyword as a modifier on constructors to prevent single-argument constructors to be used as implicit type conversion operators. However, this does nothing for actual conversion operators. For example, a smart pointer class may have an operator bool() to allow it to act more like a primitive pointer: if it includes this conversion, it can be tested with if(smart_ptr_variable) (which would be true if the pointer was non-null and false otherwise). However, this allows other, unintended conversions as well. Because C++ bool is defined as an arithmetic type, it can be implicitly converted to integral or even floating-point types, which allows for mathematical operations that are not intended by the user.
    In C++0x, the explicit keyword can now be applied to conversion operators. As with constructors, it prevents the use of those conversion functions in implicit conversions. However, language contexts that specifically require a boolean value (the conditions of if-statements and loops, as well as operands to the logical operators) count as explicit conversions and can thus use a bool conversion operator.

    Und die schreien danach, daß man alte Zöpfe abschneidet.



  • volkard schrieb:

    #include <iostream>
    #include <ctime>
    
    using namespace std;
    
    class SquareGenerator{
    	private:
    	int value_;
    	int step_;
    	public:
    	SquareGenerator(){
    		value_=1;
    		step_=1;
    	}
    	inline void step(){
    		step_+=2;
    		value_+=step_;
    	}
    	int value(){
    		return value_;
    	}
    };
    
    int main()
    {
    	int sum=0;
    	clock_t start=clock();
    	for(int o=0;o<1000000;++o){
    #if 1
    		for(int i=1;i<10000;++i)
    			sum+=i*i;
    #else
    		for(SquareGenerator s;s.value()<100000000;s.step())
    			sum+=s.value();
    #endif
    	}
    	cout<<clock()-start<<'\n';
    	cout<<sum<<'\n';
        return 0;
    }
    

    Der SquareGenerator ist langsamer, unleserlicher und nicht mal const correct. 👎 Und die Klammerung deutet auch eine gespaltene persönlichkeit hin. :p



  • ... und weitere Mehrfachbelegungen syntaktischer Elemente: extern, auto, [], und wieviele unterschiedliche Bedeutungen ":" haben wird, wer will es zählen?

    Was ich nach wie vor sehr in C++ vermisse, ist eine einfache Möglichkeit, das Typsystem zu umgehen, etwa, indem fehlende Typangaben in Variablen- und Funktionsdeklarationen implizit als ein besonderer Typ "dontcare" angenommen werden, der die Typprüfung des Compilers für diese Variable, Funktion o.ä. aufhebt, sodaß bei Bedarf für rapid prototyping ein "late bindung" Stil programmiert werden kann.

    Das wäre mal was 👍

    Was gibt es denn in C++0x Neues, das nicht in der einen oder anderen Form in der einen oder anderen Programmiersprache schon lange realisiert wäre?



  • volkard schrieb:

    Vector<int> v(5); lege ein Array an mit 5 Elementen.

    ich würde sagen, das ist kein array, sondern nur ein vector<int>, der schon mal platz für 5 elemente hat.

    volkard schrieb:

    Vector<int> v{5}; lege ein Array an mit nur einem Element, nämlich 5.

    diese schreibweise kenne ich überhaupt nicht (ist das neu, c++0x?). ein array mit nur einem element '5' würde ich (mit meinem verständnis C-ähnlicher syntaxen) so schreiben: vector<int> v[1] = {5};
    ich nehme an, c++ erlaubt auch noch den : vector<int> v[5]; also ein array, bestehend aus 5 mal vector<int>, oder nicht?

    quadratulending schrieb:

    volkard schrieb:

    #include <iostream>
    #include <ctime>
    
    using namespace std;
    
    class SquareGenerator{
    	private:
    	int value_;
    	int step_;
    	public:
    	SquareGenerator(){
    		value_=1;
    		step_=1;
    	}
    	inline void step(){
    		step_+=2;
    		value_+=step_;
    	}
    	int value(){
    		return value_;
    	}
    };
    
    int main()
    {
    	int sum=0;
    	clock_t start=clock();
    	for(int o=0;o<1000000;++o){
    #if 1
    		for(int i=1;i<10000;++i)
    			sum+=i*i;
    #else
    		for(SquareGenerator s;s.value()<100000000;s.step())
    			sum+=s.value();
    #endif
    	}
    	cout<<clock()-start<<'\n';
    	cout<<sum<<'\n';
        return 0;
    }
    

    Der SquareGenerator ist langsamer, unleserlicher und nicht mal const correct.

    langsamer isser doch nicht (hast wohl den asm-code nicht gesehen), aber er ist ein typisches beispiel für 'over engineering'. mit einem mal spielt sowas wie 'const-correctness' eine rolle (sinnlose komplexität) und aus dem leicht verständlichen zweizeiler:

    for(int i=1;...) 
      sum = sum + i*i;
    

    ca. 20 zeilen zu machen, finde ich ziemlich übertrieben. dass der asm-output annähernd gleich klein und schnell ist, wie die (völlig ausreichende) primitivlösung, ist nur volkards programmiererischem können und viel glück zu verdanken.

    u_ser-l schrieb:

    Was ich nach wie vor sehr in C++ vermisse, ist eine einfache Möglichkeit, das Typsystem zu umgehen, etwa, indem fehlende Typangaben in Variablen- und Funktionsdeklarationen implizit als ein besonderer Typ "dontcare" angenommen werden, der die Typprüfung des Compilers für diese Variable, Funktion o.ä. aufhebt, sodaß bei Bedarf für rapid prototyping ein "late bindung" Stil programmiert werden kann.

    sowas wie die variablen in PHP oder 'variant' in VB z.b.? naja, c++0x hat ja das 'auto'-keyword wiederbelebt (type inference), da bestimmt die initialisierung den typ. das geht vielleicht ein wenig in die richtung, nur dass der typ danach unglücklicherweise feststeht:

    auto someStrangeCallableType = boost::bind(&SomeFunction, _2, _1, someObject);
    

    ^^welchen typ hat 'someStrangeCallableType'? c++ programmierer werden auch künftig höchstleistungen beim gehirnjogging vollbringen müssen.
    🙂



  • +fricky schrieb:

    langsamer isser doch nicht

    lass es mal laufen



  • quadratulending schrieb:

    +fricky schrieb:

    langsamer isser doch nicht

    lass es mal laufen

    ah stimmt, die innere schleife des einen asm-codes läuft 10000 mal häufiger durch als die andere.
    🙂



  • +fricky schrieb:

    quadratulending schrieb:

    +fricky schrieb:

    langsamer isser doch nicht

    lass es mal laufen

    ah stimmt, die innere schleife des einen asm-codes läuft 10000 mal häufiger durch als die andere.
    🙂

    Ach? Mache ich wirklich solche Fehler? Ich glaube nicht.



  • Noch viel schlimmere Fehler.

    Und du hast es nicht mal geschafft um 11:22:33 Uhr zu posten.



  • u_ser-l schrieb:

    Was ich nach wie vor sehr in C++ vermisse, ist eine einfache Möglichkeit, das Typsystem zu umgehen, etwa, indem fehlende Typangaben in Variablen- und Funktionsdeklarationen implizit als ein besonderer Typ "dontcare" angenommen werden, der die Typprüfung des Compilers für diese Variable, Funktion o.ä. aufhebt, sodaß bei Bedarf für rapid prototyping ein "late bindung" Stil programmiert werden kann.

    Das wäre mal was 👍

    void* zeiger?



  • +fricky schrieb:

    langsamer isser doch nicht (hast wohl den asm-code nicht gesehen), aber er ist ein typisches beispiel für 'over engineering'. mit einem mal spielt sowas wie 'const-correctness' eine rolle (sinnlose komplexität) und aus dem leicht verständlichen zweizeiler:

    for(int i=1;...) 
      sum = sum + i*i;
    

    ca. 20 zeilen zu machen, finde ich ziemlich übertrieben.

    Nö, aus

    for(int i=1;...) 
      sum = sum + i*i;
    

    wurde

    for(SquareGenerator s;s.value()<100000000;s.step())
      sum+=i;
    

    solche generatoren benutze ich in C++ seit 15 jahren und sie machen den hauptcode code lesbarer und gelegentlich sogar erst realistisch lösbar. wenn die in haskell das dürfen, will ich das auch. und außerdem passen sie ja soo wunderar zu den ranges und range based loops, wie sollte ich da den leckerschmecker umgehen können?

    dass der asm-output annähernd gleich klein und schnell ist, wie die (völlig ausreichende) primitivlösung,

    inwiefern die gleichschnelligkeit zutrifft, sollte das programm mir zeigen. das zielprogramm wird nämlich praktisch nichts machen, außer quadratzahlen zu generieren und in einer liste abzuhaken.

    verglichen habe ich nur die methode mit IMUL gegen die Lösung C:

    //Lösung C
    for(int x=1,s=1;x<100000000;s+=2,x+=s)
       sum+=i;
    

    aber, daß die lösung C zu null mehrkosten mit einem generator aufgeschrieben werden kann, war mir so klar, daß ich sie gar nicht erst hingeschrieben habe. das ist typisch für c++, daß solche abstraktion komplett wegoptimiert wird.



  • heißt der neue standard eigentlich noch c++0x oder schon c++1x 😃



  • void* zeiger?

    Oder boost.any, dann hat man das ganze in schön.

    any dont_care_var(3);
    dont_care_var = string("hi"); 
    dont_care_var = vector<int>(3, 2);
    

    oder wie meintest du das?
    Bei der Anwendung muss man dann wieder in den richtigen Typ `casten`, aber es wäre zum Beispiel möglich eine solche Lib zu entwickeln.



  • volkard schrieb:

    solche generatoren benutze ich in C++ seit 15 jahren und sie machen den hauptcode code lesbarer und gelegentlich sogar erst realistisch lösbar. wenn die in haskell das dürfen, will ich das auch.

    Konstrukte aus fremden Sprachen verwenden - ein sicheres Zeichen, dass C++ bald ausstirbt, weil es allein nicht lebensfähig ist.



  • penis12 schrieb:

    heißt der neue standard eigentlich noch c++0x oder schon c++1x 😃

    c++0a, c++0b, c++0c...


Anmelden zum Antworten