# Anfängerfragen zu C++



## Gossi (6. Mrz 2012)

Moin, hab dazu leider bei Google nichts gefunden was mich großartig weitergebracht hätte:

Wozu sind in C++:

*  (bedeutet glaub ich Pointer, richtig?)
&  (Wenn ich richtig gesehen habe eine Referenz auf den Specherblock?)
^  (Dazu hab ich garnichts gefunden)
Wann benutze ich var.method() und wann var->method()?

Danke schonmal für die Hilfe
Gossi


----------



## kama (6. Mrz 2012)

Hi,



Gossi hat gesagt.:


> *  (bedeutet glaub ich Pointer, richtig?)
> &  (Wenn ich richtig gesehen habe eine Referenz auf den Specherblock?)
> ^  (Dazu hab ich garnichts gefunden)
> Wann benutze ich var.method() und wann var->method()?


so jetzt muss ich mal im Gedächtnis kramen...

* ist bei der Deklaration für einen Pointer richtig, aber kann auch zu dereferenzieren eines Pointer verwendet werden, was in C++ nicht so häufig vorkommen sollte...

```
DasIstEineKlasse *zeiger;
zeiger = new DasIstEineKlasse; //Default Konstruktor

(*zeiger).methode(22); //Dereferenzieren (sollte man nicht!)
zeiger->methode(22); //Besser..

DasIstEineKlasse instanz; //Ruft Default Konstruktor

instanz.methode(22);
```
& Ist die Referenz...wird üblicherweise für Referenzen auf Instanzen bzw. Variablen benutzt.

```
int anton = 12;
int egon = &anton;
```


So und dann noch zu "^" ist eine Bit-Wise XOR Operator (Operators - C++ Documentation)

PS.: Hoffe habe keine Fehler reingeschrieben..C++ ist schon ein paar Jahre her...

Gruß
Karl Heinz Marbaise


----------



## Gast2 (6. Mrz 2012)

Gossi hat gesagt.:


> Moin, hab dazu leider bei Google nichts gefunden was mich großartig weitergebracht hätte:
> 
> Wozu sind in C++:
> 
> ...



int *x deklariert einen pointer auf int
int *y = &i weist dem pointer auf integer die Adresse eines INteger namens i zu 
^ sollte Bitweise XOR sein 
var.method = var ist eine Instanz 
var->method() Kurform von (*var).method() ==> var ist ein pointer


----------



## Tomate_Salat (6. Mrz 2012)

3. Ist (wohl) auch soetwas wie ein Zeiger: Re: Was ist "^" fr ein Operator? (C-Plus-Plus)

4. Idr: bei einem Pointer nutzt du [c]->method()[/c] ansonsten [c].method()[/c]. Operatorenüberladung kann dir diese Regel [scheinbar] aber wieder "zerschießen" ;-)


----------



## Gast2 (6. Mrz 2012)

Um die Verwirrung komplett zu machen: 


```
int i = 1;
int *j = $i;
int **x = &j;
```

- i ist ein Integer mit Wert 1
- j ist ein pointer auf i 
- x ist ein pointer auf j und somit ein Pointer auf einen Pointer auf einen Integer = int **x


----------



## Gossi (6. Mrz 2012)

Ok, sehe ich das nun also richtig (was * und & angeht) =


```
int i = 5;
int *p = i;
int r = &i;

i++;
```

nun ist i = 6, p  = 5 und r = 6?

und wenn ja, ist nach:


```
p++;
r++;
```

i = 7, p = 6 und r = 7?



kappesf hat gesagt.:


> Um die Verwirrung komplett zu machen:
> 
> 
> ```
> ...



Danke, kappesf, jez weiß ich wieder was ich an C++ nicht mochte ^^

PS:



Tomate_Salat hat gesagt.:


> 3. Ist (wohl) auch soetwas wie ein Zeiger: Re: Was ist "^" fr ein Operator? (C-Plus-Plus)



Also wenn ich den Beitrag lese bedeutet das, dass * und ^ mehr oder weniger das gleiche sind, nur das ich mich bei * um die Speicherverwaltung kümmern muss und bei ^ nicht?


----------



## Tomate_Salat (6. Mrz 2012)

Gossi hat gesagt.:


> Ok, sehe ich das nun also richtig (was * und & angeht) =
> 
> 
> ```
> ...




Nein. Wenn dann müsste es heißen:

```
int i=5;
int *p=&i; // du willst ja die Pointeradresse übergeben, deswegen das &
int r=i; 

i++;
```
i ist jetzt 6. Da *p auf die Adresse von i zeigt, ist das logischerweise auch 6, also das gleiche. r bleibt 5, weil du hier nur den Wert zugewießen hast.

------
mit p++ aufpassen. Damit incrementierst du nicht den Wert, sondern den Pointer . Genauer, die adresse:

```
int i=5;
int *p=&i;
std::cout << p << std::endl;
p++;
std::cout << p << std::endl;
```
ergibt z.B.:

```
0028FCC0
0028FCC4
```

----

[EDIT]


> Also wenn ich den Beitrag lese bedeutet das, dass * und ^ mehr oder weniger das gleiche sind, nur das ich mich bei * um die Speicherverwaltung kümmern muss und bei ^ nicht?


Ja kann sein. Da ich nicht mit CLI arbeite, kann ich das aber nicht wirklich beurteilen.
[/EDIT]


----------



## Gast2 (6. Mrz 2012)

Gossi hat gesagt.:


> Ok, sehe ich das nun also richtig (was * und & angeht) =
> 
> 
> ```
> ...



Um Gottes Willen NEIN!!!! 

p zeigt so auf *Adresse *5!
Ein Pointer ist intern nichts weiter als eine Zahl. Wenn du einem Pointer einn INteger zuweist (ja das geht in C++ wegen Zeiger Arithmetik!) dann zeigt der Pointer p auf die Adresse 5 wie gesagt. 

Möchtest du, dass der Pointer auf i zeigt musst du den Pointer mit der Adresse von i (&i) initialisieren!

Wenn du dann im übrigen p ausgibst ist das nicht die Zahl von i sondern die Adresse! Willst du die Zahl des Integer auf die p zeigt musst du (*p) ausgeben!


----------



## Gossi (6. Mrz 2012)

Tomate_Salat hat gesagt.:


> Nein. Wenn dann müsste es heißen:
> 
> ```
> int i=5;
> ...



Meine Güte...danke ersmtmal für die Hilfe, und ich dachte das Klassen schreiben wäre hier so beschissen (im vergleich zu Java), freue mich schon auf Morgen oder Donnerstag, da wollte ich mir Speicherverwaltung anschauen 

PS:



Tomate_Salat hat gesagt.:


> mit p++ aufpassen. Damit incrementierst du nicht den Wert, sondern den Pointer . Genauer, die adresse:
> 
> ```
> int i=5;
> ...



Könnte gefährlich werden ^^



kappesf hat gesagt.:


> Um Gottes Willen NEIN!!!!
> 
> p zeigt so auf *Adresse *5!
> Ein Pointer ist intern nichts weiter als eine Zahl. Wenn du einem Pointer einn INteger zuweist (ja das geht in C++ wegen Zeiger Arithmetik!) dann zeigt der Pointer p auf die Adresse 5 wie gesagt.



Dann hätte schreiben müssen [c]int *p = &i[/c], wie Tomtae_Salat meinte, richtig?


----------



## Gast2 (6. Mrz 2012)

Denk auch dran, dass es keinen Garbage COllector gibt! Du musst an jeden free denken und solltest auch höllisch auf saubere Destruktoren aufpassen! 

Mach am besten ein Tutorial zu Pointer Referencen und Variablen! Das ist nicht so ohne ...



> Deswegen ja auch p = 5 und r = 6, aber dafür hätte ich dann schreiben müssen int *r = &i oder?



p bzw. r wäre dann immer noch der Wert der Adresse! Willst du den Pointer dereferenzieren geht das nur mit (*p) bzw (*r) 

Beispiel: 

```
int i = 5; // Imaginäre Adresse von i = 0xFF365489
int *p = &i;
```

Dann ist i=5 
p = 0xFF365489
und (*P) = 5

[OT]Was denkst du wieso ich Java so toll finde? ^^ In c++ gibts auch keine so schöne API. Und da ich viel Platformunabhängiges Zeug schreibe durften wir erst mal selber Bibliotheken zum abstrahieren des OS schreiben.[/OT]


----------



## Gast2 (6. Mrz 2012)

```
Dann hätte schreiben müssen int *p = &i , wie Tomtae_Salat meinte, richtig?
```

Ja, denn sonst verpasst du dem Pointer als Adresse den *Wert* des int. Das wird NICHT abgefangen da es wie gesagt zulässig ist einen pointer zu inkrementieren. 

int *p = &i; 

p z.B. 0xFF354758

nach p++; ist p dann 0xFF354759. Das gibt dann schöne Runtime Exceptions im besten Fall. Im schlimmsten ist der Speicherplatz zulässig und du zerschießt dir was auch immer da lag!


----------



## Gossi (6. Mrz 2012)

Das würde auch den Bluescreen erklären den ich vor rund 5 minuten hatte, wobei, bei dem Code, dürfte er dann doch nichts verändern, oder?


```
int i = 23;
int *p = i;
p++;
delete p;
```

Oder hat er in dem Fall den Speicherblock 24 gelöscht?


----------



## Gast2 (6. Mrz 2012)

Gossi hat gesagt.:


> Das würde auch den Bluescreen erklären den ich vor rund 5 minuten hatte, wobei, bei dem Code, dürfte er dann doch nichts verändern, oder?
> 
> 
> ```
> ...



Er würde den Speicherblock 24 löschen. Das geht aber nicht, da deine Applikation da sicher keine Schreib/Leserechte hat. Dann fliegt eine Runtime Exception und die Software schmiert weg. 

Schlimm ist es allerdigs wenn die falsche Adresse im Adressbereich der Applikation liegt. Dann zerschießt du dir Daten. Das passiert z.B. wenn du einen Pointer auf ein Objekt a legst. a wird woanders freigegeben und an anderer Stelle derefenzierst du a nochmal und schreibst an die Speicherstelle als gäbe es a noch. Wenn der Bereich inzwischen anderweitig genutzt wurde fliegt kein Fehler und du hast das neue Objekt korrumpiert. So Fehler zu finden ist ein Alptraum!


----------



## Gossi (6. Mrz 2012)

Der komplette Code wäre gewesen:



```
int *p = 0;
bool proceed = true;
while(proceed) {
     int i = userEingabe();
     if(i > 123) {
          proceed = false;
          *p = i;
     }
}
cout << "Eingabe: " << p << endl;
delete p;
```

Wollte da mal rumtesten, auch wenn der Code und der Test idiotisch sind xD

PS: Grade nochmal ausgeführt, diesmal gabs nur ne Runtime...


----------



## Gast2 (6. Mrz 2012)

So wäre richtig:


```
int *p = null;
bool proceed = true;
while(proceed) {
     int i = userEingabe();
     if(i > 123) {
          proceed = false;
          *p = &i;
     }
}
if (p) {
     cout << "Eingabe: " << (*p) << endl;
    delete p;
}
```


----------



## Gossi (6. Mrz 2012)

Eigentlich hatte ich auch mit ner Exception gerechnet...aber nicht mit nem BlueScreen


----------



## Tomate_Salat (6. Mrz 2012)

Muss man so einen Pointer: 

```
int a=5;
int *p=&a;
```

wirklich mit delete freigeben? Der Speicher sollte doch nach verlassen des Scopes von [c]a[/c] wieder freigegeben werden. Afaik enstehen doch die berüchtigten Speicherlöcher, wenn man vergisst Pointer aufzuräumen, die mit 
	
	
	
	





```
new
```
 erstellt worden sind.


----------



## Gast2 (6. Mrz 2012)

Tomate_Salat hat gesagt.:


> Muss man so einen Pointer:
> 
> ```
> int a=5;
> ...



Hast natürlich Recht. Da hab ich mich selber reingelegt ^^ 
Klar der Speicher wurde ja nicht durch ein new sondern durch deklaration eines Integer allokiert.


----------



## Gossi (6. Mrz 2012)

Tomate_Salat hat gesagt.:


> Muss man so einen Pointer:
> 
> ```
> int a=5;
> ...



Also müsste ich:


```
Konto *k = new Konto(1500.21, 25589642, 27050101, "Vorname", "Nachname", -500.00);
```

mit delete freigeben,


```
int i = 5;
int *p = &i;
```

hingegen nicht?


----------



## Tomate_Salat (6. Mrz 2012)

Jup. 
[c]int i=5;[/c]
Der Speicher wird hier freigeben, sobald der Scope verlassen wird. Wenn du aber Speicher mit einem [c]new[/c] allocierst, wird der Speicher nach verlassen des Scopes nicht freigegeben (außer du deletest es).

Was man noch beachten sollte:
Speicher freigeben heißt *nicht* dass der Wert gelöscht wird. Deswegen ist es z.B. in C++ notwendig, neue Variablen auch zu definieren:
[c]int i;[/c]
lässt du das so, hast du eine sehr sehr seh hohe wahrscheinlichkeit, dass in i irgendein Datenmüll drinsteht.


----------



## Gossi (6. Mrz 2012)

-.- ich hasse C++ immer mehr, je mehr ich mich damit beschäftige xD


----------



## Fu3L (6. Mrz 2012)

Und wenn du dann das erste Programm fertig hast, dein System neu aufsetzen musst und die nötige Bibliothek sich nicht mehr einbinden lässt (was in C++ ja weniger leicht ist als in Java), dann wirst du dir entnervt eine Signatur wie meine zulegen^^


----------



## KuhTee (6. Mrz 2012)

Ach ja... die Jammerlappen mal wieder 

Heute hab ich gelesen, dass fast die Hälfte aller Kinder nicht mehr in der Lage sind sich die Schuhe selbst zu binden. Und die Hälfte aller Java Programmier sind nicht in der Lage einfache Pointer-Arithmetik zu verstehen 

Aber ehrlich gesagt würde ich es auch nicht empfehlen, Pointer in C++ anhand von konstruierten Beispielen zu erlernen nur um des Lernens Willen, obwohl du es ja offenbar gar nicht wirklich willst. Klingt für mich alles sehr erzwungen hier, Schule oder Ausbildung?

Ausserdem fehlen hier glaube ich andere grundlegende Kenntnisse hinsichtlich Scope von Variablen, Unterschied zwischen Stack und Heap etc. Ich denke, man sollte zuerst das verstehen, bevor man wild anfängt zu referenzieren und zu dereferenzieren.

Aber zugegeben: es dauerte auch bei mir ein Weilchen bis es "klick" macht und man das Rumhantieren mit Pointern korrekt versteht. Aber es eröffnet einem auch eine Menge Möglichkeiten. Ich zB habe sehr gern für den Gameboy Advance programmiert, und versucht da mal Java laufen zu lassen


----------



## Gossi (7. Mrz 2012)

KuhTee hat gesagt.:


> Ach ja... die Jammerlappen mal wieder
> 
> *Achja, die Klugs*****er mal wieder :bae:*
> 
> ...



Geht bestimmt auch.


----------



## Tomate_Salat (7. Mrz 2012)

> Aber es eröffnet einem auch eine Menge Möglichkeiten.


Da hast du Recht. Vor allem die Möglichkeit auf eine MemoryLeakFactory  scnr.


----------



## Gossi (7. Mrz 2012)

Tomate_Salat hat gesagt.:


> Da hast du Recht. Vor allem die Möglichkeit auf eine MemoryLeakFactory  scnr.



:toll:

So, mittlerweile habe ich mich auch ein bisschen in C++ eingefunden, auch wenn ich momentan nur an den Basics kratze ^^


----------



## KuhTee (7. Mrz 2012)

Gossi hat gesagt.:


> ...ich bin mir über den Scope von Variablen sehr wohl im klaren, da dieser sich bei C++ und Java nicht (minimal) unterscheidet


In Kombination mit Heap/Stack gibt es da schon Unterschiede, zumindest bei den Objekten. Und auch Pointer können da, wenn das Verständnis fehlt, schnell zum Fallstrick werden. Hab zB schon häufiger gesehen, dass die Leute einfach vergessen oder es Ihnen schlicht nicht klar ist, dass der Pointer bei "call by reference" natürlich trotzdem "call by value" übergeben wird.


----------



## Gast2 (7. Mrz 2012)

Tomate_Salat hat gesagt.:


> Da hast du Recht. Vor allem die Möglichkeit auf eine MemoryLeakFactory  scnr.



Da ist natürlich was wahres dran aber ich muss mal für Java als auch für C++ eine Lanze brechen:

Beide Sprache sind in ihren jeweiligen Anwenungsgebieten unschlagbar wenn es um portierbarkeit geht. Die Frage ist eben was man machen muss. Serverseitig ist es definitiv Java und auch bei einfachen Desktopapplikationen für Endkunden punktet Java einfach aufgrund der umfangreichen API. 

Wenn es in Richtung System und Embedded Programmierung geht ist C++ das Maß aller Dinge (Ich schließe hier natürlich C mit ein). Nach wie vor! (Ausnahmen Smartphones) Auch hier gibt es jede Menge Frameworks, man muss nur halt mühsam alles was man braucht selber zusammentragen. Für viele Probleme wie z.B. MemoryLeaks gibts zumindest Workarounds (Boost SmartPtr z.B., auch wenn einen die nicht von der Verantwortung entbinden) und vieles mehr. 

Weder das eine noch das andere ist perfekt. Sich in beidem auszukennen erzeugt aber imho sehr viele Synergien, da man eben Schwachstellen beider Philosophhien kennt und daher auch ein viel besseres Verständnis für die Probleme erhält. Vieles aus meiner C++ Arbeit und Erfahrung kann ich in Java einbringen aber umgekehrt finden viele Dinge aus Java auch in C++ Anwendung. 

Also bitte nicht noch ein "Wir diskutieren mal was besser ist" Thread!


----------



## Marco13 (7. Mrz 2012)

Ich denke auch, dass es Vorteile haben kann, sich in beidem etwas auszukennen (und bei einigen der Antworten auf die ursprünglichen Fragen lief es mir kalt den Rücken runter :autsch:  ). Zugegeben, sowas wie der Unterschied zwischen
int *a = &b;
und 
int& x = y;
kann schon verwirrend sein. Ich denke, dass ein paar Grundkenntnisse in C/C++ (auch und _gerade_ die Pointersachen) hilfreich sein können - zumal man sagen könnte, dass Java in dieser Hinsicht einfach "weniger" ist: Eine Referenz in Java ist eigentlich ein C++-Pointer, aber eben OHNE den syntaktischen Clutter wie *(*(&x))->foo((void**)&y) und natürlich ohne Pointerarithmetik. Dass die Begriffe "Referenz" in Java und C++ damit _komplett_ unterschiedliche Bedeutungen haben, macht einiges vielleicht schwerer, aber ... darüber nachzudenken, und sich die Bedeutungen und Unterschiede klarzumachen, ist so eine Art _Abhärtung_ :smoke: 

Und um die Diskussion zu der Frage, welche Sprache besser ist, mal wieder etwas anzuheizen :joke: : Ich vermisse schon so Sachen wie

```
int *a = new int[100];
compute(a+25, 50); // Rechne auf den Mittleren (!) 50 Elementen rum
```
oder die "brutale Allgemeingültigkeit" eines void*-Pointers, der auf jeden beliebigen rohen Speicherblock zeigen kann. Aber man kann eben viel K***e damit machen.

Zumindest habe ich gemerkt, dass ich (nachdem ich lange praktisch nur Java programmiert habe) immer wenn ich etwas in C++ mache, einen sehr Java-haften Stil verwende...


----------



## Gast2 (7. Mrz 2012)

> Zumindest habe ich gemerkt, dass ich (nachdem ich lange praktisch nur Java programmiert habe) immer wenn ich etwas in C++ mache, einen sehr Java-haften Stil verwende...



Kann ich bestätigen. Vor allem was Umsetzungen der allgemeinen Design Patterns betrifft orientiere ich mich häufig an den Java Implementationen. Mehrfachvererbung vermeide ich wenn es nur irgend geht und verwende auch in C++ Interfaces. Es gibt zwar an und für sich keine Interfaces aber eben abstrakte Klassen. Und was anderes ist ein Interface ja auch nicht ^^


----------



## Tomate_Salat (7. Mrz 2012)

kappesf hat gesagt.:


> Mehrfachvererbung vermeide ich wenn es nur irgend geht



Ey stimmt, dito. Ich wusste, dass es sowas in C++ gibt aber verdränge es wohl^^. Bei VC++ gibt es im übrigen interfaces: __interface (C++)


----------



## Gossi (7. Mrz 2012)

C++-Code (funktioniert nicht, hat wohl probleme mit int[] als Rückgabewert):


```
int[] getPrimZahl(int max) {
    int primzahlen[max];
    int count = 0;
    for(int i = 0; i <= max; i++) {
        if(isPrimzahl(i)) {
            primzahlen[count] = i;
            count ++;
        }
    }
    int size = sizeof( primzahlen ) / sizeof( primzahlen[0] );
    int returnArray[size];
    for(int i = 0; i <= size; i++) {
        if(primzahlen[i] != NULL && primzahlen[i] != 0) {
            returnArray[i] = primzahlen[i];
        } else {
            break;
        }
    }
    return returnArray;
}
```

Das gleiche in Java:


```
int[] getPrimZahl(int max) {
    int primzahlen[max];
    int count = 0;
    for(int i = 0; i <= max; i++) {
        if(isPrimzahl(i)) {
            primzahlen[count] = i;
            count ++;
        }
    }
    int returnArray[primzahlen.length];
    for(int i = 0; i <= primzahlen.length; i++) {
        if(primzahlen[i] != NULL && primzahlen[i] != 0) {
            returnArray[i] = primzahlen[i];
        } else {
            break;
        }
    }
    return returnArray;
}

//oder schöner:

List<Integer> getPrimZahlen(int max) {
    List<Integer> returnList = new ArrayList<Integer>();
    for(int i = 0; i <= max; i++) {
        if(isPrime(i)) {
            returnList.add(i);
        }
    }
    return returnList;
}
```


----------



## Gast2 (7. Mrz 2012)

Tomate_Salat hat gesagt.:


> Ey stimmt, dito. Ich wusste, dass es sowas in C++ gibt aber verdränge es wohl^^. Bei VC++ gibt es im übrigen interfaces: __interface (C++)



Das ist nicht in C++. Das ist proprietär von Microsoft und daher sehr mit Vorsicht zu genießen. Diese Dinger benötigen meistens ein .net framework oder die Visual Studio redistributables. 

Man sollte sich wenn man auch auf Embedded targets hin entwickelt wirklich an quellofene Dinge halten (Boost, pugixml, openvpn, ...) und natürlich die basics aus der STL


----------



## Gast2 (7. Mrz 2012)

Gossi hat gesagt.:


> C++-Code (funktioniert nicht, hat wohl probleme mit int[] als Rückgabewert):
> 
> 
> ```
> ...



Das geht nicht. Arrays müssen in C++ statisch initialisiert werden. Das geht nicht dynamisch! 

Verwende die Containerklassen aus der STL für solche Dinge! Arrays sind böse!


----------



## Tomate_Salat (7. Mrz 2012)

kappesf hat gesagt.:


> Das ist nicht in C++.



Deswegen hab ich geschreiben: Bei *VC++*. (Kann mich irren, aber afaik steht VC++ für Visual C++ und setzt somit Visual Studio und deren mitgelieferten Compiler vorraus)


----------



## Gast2 (7. Mrz 2012)

Tomate_Salat hat gesagt.:


> Deswegen hab ich geschreiben: Bei *VC++*. (Kann mich irren, aber afaik steht VC++ für Visual C++ und setzt somit Visual Studio und deren mitgelieferten Compiler vorraus)



Ups überlesen! Hast natürlich Recht. Aber wer macht das schon? Ich verwende zwar VS als Editor Compiler und Debugger aber ich verwende keine VC++ Libraries zwecks portierbarkeit!


----------



## Fu3L (7. Mrz 2012)

> Verwende die Containerklassen aus der STL für solche Dinge! Arrays sind böse!



Das finde ich persönlich so Schade an C++: Man bekommt alle möglichen Hilfsmittel (zB Arrays). Man baut was damit und denkt: "Bin ich cool, es tut". Im nächsten Moment kommt jemand mit etwas mehr Erfahrung und sagt: "Neee, so macht man das aber nicht"... Ich habn Anfängerbuch über C++ gelesen und da standen solche Sachen mit keiner Silbe erwähnt.
Deswegen bin ich zu dem Schluss gekommen, dass ich C++ erst (weiter)lerne, wenn ich wirklich mal die Zeit dazu habe, weil man einfach so viel (wenig) offensichtliches beachten muss.


----------



## Gast2 (7. Mrz 2012)

Achtung folgende Aussagen beziehen sich auf Command Line Programmierung für Multi Target (auch Embedded): 

Imho ist es nur möglich guten C++ Code zu schreiben wenn man sich gut in der STL und der Boost auskennt, da viele Dinge die einfach notwendig sind anders nur durch Krücken zu erreichen sind. 
Die STL gehört zum C++ Standard, wird aber auch meiner Meinung nach in Büchern viel zu wenig integriert. Um ein gutes Buch zur STL kommt man daher eigentlich nicht drum herum. 
Da aber selbst die STL viel zu wenig bietet was man heute braucht empfiehlt sich die Boost. Dort ist das meiste realsiert (z.B. Smart Pointer, Serialisierung) und vieles vieles mehr.

Ein so schönes Set fertiger APIs wie in Java gibts halt nicht.


----------



## Marco13 (7. Mrz 2012)

kappesf hat gesagt.:


> Das geht nicht. Arrays müssen in C++ statisch initialisiert werden. Das geht nicht dynamisch!
> 
> Verwende die Containerklassen aus der STL für solche Dinge! Arrays sind böse!



Das "Problem" bei STL-Klassen ist dann, dass da Dinge wie der Zuweisungsperator und der CopyKonstruktor verwendet werden, ohne dass man es sieht (oder sich bewußt macht). Wenn man einen "großen" STL-vector<int> irgendwo zurückgibt, wird er AFAIR kopiert. Abhilfe wäre dann, einen Zeiger zurückzugeben. Aber wer gibt ihn wieder frei? (Pfuh ... da lob ich mir doch Java <3  )


----------



## Gast2 (7. Mrz 2012)

Marco13 hat gesagt.:


> Das "Problem" bei STL-Klassen ist dann, dass da Dinge wie der Zuweisungsperator und der CopyKonstruktor verwendet werden, ohne dass man es sieht (oder sich bewußt macht). Wenn man einen "großen" STL-vector<int> irgendwo zurückgibt, wird er AFAIR kopiert. Abhilfe wäre dann, einen Zeiger zurückzugeben. Aber wer gibt ihn wieder frei? (Pfuh ... da lob ich mir doch Java <3  )



Du hast Recht. Und das lässt sich in C++ generell so zusammenfassen: 
Man hat viel mehr Verantwortung zu tragen!


----------



## Gossi (7. Mrz 2012)

So, hab nochmal ne frische Fuhre Anfängercode, wollte das umbedingt vorm Feierabend durch haben...


```
list<int> primes = getPrimzahlen(10);
    list<int>::iterator iterPrime = primes.begin();
    while( iterPrime != primes.end() ) {
        list<int>::iterator thisone = iterPrime;
        iterPrime++;
        cout << *thisone << " ist eine Primzahl" << endl;
    }
```


```
list<int> getPrimzahlen(int max) {
    list<int> returnList;
    for(int i = 0; i <= max; i++) {
        if(isPrimzahl(i)) {
            returnList.push_back(i);
        }
    }
    return returnList;
}
```


```
bool isPrimzahl(int kandidat) {
    for(int i = 2; i < kandidat; i = i + 1) {
        if(kandidat % i == 0) {
            return false;
        }
    }
    return true;
}
```

Ales nicht schön, aber es funzt...


----------



## schalentier (7. Mrz 2012)

Marco13 hat gesagt.:


> Das "Problem" bei STL-Klassen ist dann, dass da Dinge wie der Zuweisungsperator und der CopyKonstruktor verwendet werden, ohne dass man es sieht (oder sich bewußt macht). Wenn man einen "großen" STL-vector<int> irgendwo zurückgibt, wird er AFAIR kopiert. Abhilfe wäre dann, einen Zeiger zurückzugeben. Aber wer gibt ihn wieder frei? (Pfuh ... da lob ich mir doch Java <3  )



Korrekt, das wurde inzwischen wohl auch von den C++ "Goettern" erkannt. Deswegen gibt es im C++11 Standard nun auch einen Move-Konstruktor. In Kombination mit shared_ptr und unique_ptr (beides imho inzwischen auch in der STL, wenn nicht, dann bald) kann man wohl in den meisten Faellen auf Pointer und vor allem new und delete verzichten. 

@Gossi: Anstatt [c]list<int>[/c] verwende lieber [c]vector<int>[/c].


----------



## Marco13 (7. Mrz 2012)

Als kleiner Einwurf, der sowohl zu STL als auch zu Primzahlen passt: stl/prime1.cpp (siehe auch die anderen Beispiele auf The C++ Standard Library: Index - mit der STL kann man einige ziemlich magische Sachen machen  )


----------



## Gossi (8. Mrz 2012)

schalentier hat gesagt.:


> @Gossi: Anstatt [c]list<int>[/c] verwende lieber [c]vector<int>[/c].



Okay, gibts da auch ne Begründung für? ^^


----------



## Gast2 (8. Mrz 2012)

Ich würde das nicht so pauschal sagen. 

std::list ist eine doppelt verkettete Liste - Einfügen an beliebiger Stelle geht sehr schnell aber es ist aufwendiger, einen bestimmten Datensatz per Index anzusprechen.

std::vector ist ein Array mit dynamischer Länge - Elemente sind sehr schnell zu erreichen, aber einfüge oder Löschoperationen am Anfang dauern entsprechend länger.


----------



## schalentier (8. Mrz 2012)

kappesf hat gesagt.:


> Ich würde das nicht so pauschal sagen.
> 
> std::list ist eine doppelt verkettete Liste - Einfügen an beliebiger Stelle geht sehr schnell aber es ist aufwendiger, einen bestimmten Datensatz per Index anzusprechen.
> 
> std::vector ist ein Array mit dynamischer Länge - Elemente sind sehr schnell zu erreichen, aber einfüge oder Löschoperationen am Anfang dauern entsprechend länger.



Nein, eben nicht. Ich zitier mich mal selbst: http://www.java-forum.org/plauderecke/22639-java-quiz-75.html#post868404

LinkedList (std::list) ist nur dann schneller, wenn man (ausschliesslich) am Anfang oder am Ende einfuegt.  Also nur dann, wenn man einen Stack oder eine Queue verwendet. In allen anderen Faellen ist std::vector (deutlich) performanter und vor allem skalierbarer. Die Geschwindigkeit (Einfuegen und Loeschen) in einer LinkedList sinkt exponentiell mit der Groesse. Ich wuerd mir einfach von Anfang an angewoehnen, den vector zu nehmen ;-)

Wenn du dir mal bisschen (guten) C++ Quellcode ansiehst, wirst du feststellen, dass fast immer std::vector benutzt wird.


----------



## Gast2 (8. Mrz 2012)

schalentier hat gesagt.:


> Nein, eben nicht. Ich zitier mich mal selbst: http://www.java-forum.org/plauderecke/22639-java-quiz-75.html#post868404
> 
> LinkedList (std::list) ist nur dann schneller, wenn man (ausschliesslich) am Anfang oder am Ende einfuegt.  Also nur dann, wenn man einen Stack oder eine Queue verwendet. In allen anderen Faellen ist std::vector (deutlich) performanter und vor allem skalierbarer. Die Geschwindigkeit (Einfuegen und Loeschen) in einer LinkedList sinkt exponentiell mit der Groesse. Ich wuerd mir einfach von Anfang an angewoehnen, den vector zu nehmen ;-)
> 
> Wenn du dir mal bisschen (guten) C++ Quellcode ansiehst, wirst du feststellen, dass fast immer std::vector benutzt wird.



Ich habe nur gesagt man darf es nicht pauschalisieren!
Ich verwende selber zu 95% std::vector. Einem Neuling sollte man dennoch nicht generell von einer Collection abraten, sondern die Unterschiede aufzeigen. Du hast jedoch Recht, ich hätte noch darauf hinweisen sollen, dass bis auf Ausnahmen vector die bessere Wahl ist.


----------



## Gossi (9. Mrz 2012)

So, nu werden die Benutzereingaben über ne Datei gehändelt, für Verbesserungen bin ich immer offen:


```
int main()
{
    int max = 0;
    fstream in;
    in.open("test.txt", ios::in);
    in >> max;
    in.close();
    vector<int> primes = getPrimzahlen(max);
    vector<int>::iterator iterPrime = primes.begin();
    cout << endl << "Druecken sie eine Taste um die Primzahlen anzuzeigen" << endl;
    while(!kbhit()) {
        Sleep(100);
    }
    getch();
    fstream out;
    out.open("test.txt", ios::out);
    out << max << endl;
    while( iterPrime != primes.end() ) {
        vector<int>::iterator thisone = iterPrime;
        iterPrime++;
        out << *thisone << " ist eine Primzahl" << endl;
        cout << *thisone << " ist eine Primzahl" << endl;
    }
    out.close();
}
```

Die Datei:

Vorher:

```
20
```

Nachher:

```
20
0 ist eine Primzahl
1 ist eine Primzahl
2 ist eine Primzahl
3 ist eine Primzahl
5 ist eine Primzahl
7 ist eine Primzahl
11 ist eine Primzahl
13 ist eine Primzahl
17 ist eine Primzahl
19 ist eine Primzahl
```


----------



## AlexSpritze (9. Mrz 2012)

Gossi hat gesagt.:


> [..] für Verbesserungen bin ich immer offen:
> 
> Nachher:
> 
> ...



Naja, 0 und 1 sind keine Primzahlen


----------



## Gossi (9. Mrz 2012)

AlexSpritze hat gesagt.:


> Naja, 0 und 1 sind keine Primzahlen



Meckerziege, wurde nun gefixt ^^


----------



## AlexSpritze (11. Mrz 2012)

Und dann wär noch die Frage nach

```
while(!kbhit()) {
        Sleep(100);
    }
```

Sieht aus, als ob du da pollst. Kann man das nicht auch eleganter lösen? Da müssten dann wohl die C++-Experten ran.


----------



## Gossi (12. Mrz 2012)

AlexSpritze hat gesagt.:


> Sieht aus, als ob du da pollst. Kann man das nicht auch eleganter lösen? Da müssten dann wohl die C++-Experten ran.



Des war leider die einfachste Lösung die ich gefunden habe um auf einen Tastendruck zu warten...


----------



## Gossi (12. Mrz 2012)

Mal eine Frage, gibt es in C++ eine schnellere Lösung um festzustellen, ob eine Zahl eine Primzahl ist, als so?


```
bool isPrimzahl(int kandidat) {
    for(int i = 2; i < kandidat; i++) {
        if(kandidat % i == 0) {
            return false;
        }
    }
    return true;
}
```


----------



## Illuvatar (12. Mrz 2012)

Meinst du schneller im Sinne von "mit weniger Code" oder "mit kürzerer Laufzeit"?
Du müsstest zum Beispiel die Schleife nur bis zur Wurzel von [c]kandidat[/c] laufen lassen, das braucht aber natürlich mehr Code  Abgesehen davon gibt es auch noch ausgefeiltere Algorithmen.


----------



## Marco13 (12. Mrz 2012)

PRIMES is in P - PFD-Datei


----------



## Gossi (12. Mrz 2012)

Illuvatar hat gesagt.:


> Meinst du schneller im Sinne von "mit weniger Code" oder "mit kürzerer Laufzeit"?
> Du müsstest zum Beispiel die Schleife nur bis zur Wurzel von [c]kandidat[/c] laufen lassen, das braucht aber natürlich mehr Code  Abgesehen davon gibt es auch noch ausgefeiltere Algorithmen.



Hmm, ok, werd ich mir mal anschauen, das pdf-Dokument les ich mir auch mal durch....

Hab jetzt einfach mal (schön blöd, dass ich das vorher nicht gesehen habe, die Funktion leicht umgeschrieben:


```
bool isPrimzahl(int kandidat) {
    int halfKandidat = kandidat / 2;
    for(int i = 2; i < halfKandidat; i++) {
        if(kandidat % i == 0) {
            return false;
        }
    }
    return true;
}
```

Und siehe da:

129.719 s vorher
64.938 s nachher, immerhin schonmal etwas...


----------



## Illuvatar (12. Mrz 2012)

Gossi hat gesagt.:


> ```
> int halfKandidat = kandidat / 2;
> ```



(Abgerundete) Quadratwurzel genügt sogar  Ich weiß grad aber nicht mehr, wie die Funktion in C++ heißt.


----------



## Gossi (12. Mrz 2012)

Wobei ich bei meiner "neuen Version" eine Primzahl mehr habe als in der alten ???:L

Edit:

```
int halfKandidat = (kandidat / 2) + 1;
```
Funktioniert ^^

Edit 2:
So, eine weitere Verbesserung (auf unter 1 sekunde bei Primzahlen bis 1.000.000):

```
double halfKandidat = sqrt(kandidat+1);
```
Bei kandidat, anstelle von kandidat+1 bekomme ich leider unstimmigkeiten bei den Primzahlen, aber so läufts ^^


----------



## Gossi (12. Mrz 2012)

So, wers einmal selber testen will, oder über den Quellcode motzen will 

Main:

```
#include "Prime.hpp"

using namespace std;

int main()
{
    int max = 1000000;
    Prime *prim = new Prime();
    prim->showAndWritePrimzahlen(max, prim->getPrimzahlen(max));
}
```

Prime.hpp:

```
#ifndef PRIME_HPP_INCLUDED
#define PRIME_HPP_INCLUDED
#include <vector>
#include <fstream>
#include <math.h>
#include <iostream>

using namespace std;

class Prime {

    public:
        Prime();
        ~Prime();

        bool isPrimzahl(int kandidat);
        vector<int> getPrimzahlen(int max);
        void writePrimzahlen(int max, vector<int> primes);
        void showPrimzahlen(vector<int> primes);
        void showAndWritePrimzahlen(int max, vector<int> primes);

};

#endif // PRIME_HPP_INCLUDED
```

Prime.cpp:

```
#include "Prime.hpp"

Prime::Prime() {}

Prime::~Prime() {}

bool Prime::isPrimzahl(int kandidat) {
    double halfKandidat = sqrt(kandidat+1);
    for(int i = 2; i < halfKandidat; i++) {
        if(kandidat % i == 0) {
            return false;
        }
    }
    return true;
}

vector<int> Prime::getPrimzahlen(int max) {
    vector<int> returnList;
    if(max >= 100) {
        int berechne = 0;
        int mod = max / 100;
        for(int i = 2; i <= max; i++) {
            if(i % mod == 0) {
                if(berechne < 10) {
                    cout << "Berechne: 00" << berechne << "% abgeschlossen" << endl;
                } else if(berechne < 100) {
                    cout << "Berechne: 0" << berechne << "% abgeschlossen" << endl;
                } else {
                    cout << "Berechne: " << berechne << "% abgeschlossen" << endl;
                }
                berechne += 1;
            }
            if(isPrimzahl(i)) {
                returnList.push_back(i);
            }
        }
    } else {
        for(int i = 2; i <= max; i++) {
            if(isPrimzahl(i)) {
                returnList.push_back(i);
            }
        }
    }
    return returnList;
}

void Prime::writePrimzahlen(int max, vector<int> primes) {
    vector<int>::iterator iterPrime = primes.begin();
    fstream out;
    out.open("test.txt", ios::out);
    out << max << endl;
    while( iterPrime != primes.end() ) {
        vector<int>::iterator thisone = iterPrime;
        iterPrime++;
        out << *thisone << " ist eine Primzahl" << endl;
    }
    out.close();
}

void Prime::showPrimzahlen(vector<int> primes) {
    vector<int>::iterator iterPrime = primes.begin();
    while( iterPrime != primes.end() ) {
        vector<int>::iterator thisone = iterPrime;
        iterPrime++;
        cout << *thisone << " ist eine Primzahl" << endl;
    }
}

void Prime::showAndWritePrimzahlen(int max, vector<int> primes) {
    showPrimzahlen(primes);
    writePrimzahlen(max, primes);
}
```


----------



## schalentier (12. Mrz 2012)

Regel Nummer 1:

new und delete vermeiden!


```
int main()
{
    int max = 1000000;
    Prime prim();
    prim.showAndWritePrimzahlen(max, prim.getPrimzahlen(max));
}
```

Regel Nummer 2:
In C++ machst du immer Call by Value per default. D.h. sowohl in deinem getPrimzahlen(), als auch in allen andren Methoden, wird der vector<int> IMMER kopiert!

Besser waere in deinem Fall, den vector<int> als Feld direkt in die Klasse Prime zu packen.


----------



## Fu3L (12. Mrz 2012)

Meine Java Implementierung braucht 11 Millisekunden ohne Ausgaben... Wenn du das schlägst, bist du mittelmäßig  (Kleiner Anreiz sich Marcos Link anzusehen oder Wikipedia oder andere Quellen  )

Edit: Ich werfe mal das Stichwort "sieve of Eratosthenes" dazu^^  Wäre vllt ganz interessant zu sehen, wie der Performanceunterschied dann tatsächlich ist zwischen Java und C++ in so einer Aufgabe.


----------



## Gossi (13. Mrz 2012)

So, mit Recherche im Internet hab ich meine Suche nun (bei 1.000.000 Zahlen) von von rund 500ms auf 50 bis 80 ms reduzieren....mal sehen, vielleicht finde ich ja noch mehr ^^

PS:
Wieviele Primzahlen findest du bis 1.000.000?

Edit:
Ausgabe bei meinem Programm:

```
Zeit: 32ms
Zeit: 15ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 46ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 46ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 47ms
Zeit: 46ms
```
Zeit steht hierbei für die Berechnung der Primzahlen bis 1.000.000



Fu3L hat gesagt.:


> Meine Java Implementierung braucht 11 Millisekunden ohne Ausgaben...



???:L wie schaffst du in Java 11ms?


----------



## Fu3L (13. Mrz 2012)

Das ist schonmal kein schlechter Wert 
78498 Stück dürften es sein. Werde vllt heute Abend mal vergleichend die CPP Version meiner Java Implementierung testen, die ich grad wiederfand^^ (Grad keinen Compiler drauf) 
Dann sehen wir auch, ob ich die nur schaffe, weil mein neuer PC cool ist^^


----------



## Gossi (13. Mrz 2012)

Fu3L hat gesagt.:


> [...]weil mein neuer PC cool ist^^



Cooler als mein Arbeitsrechner bestimmt (PS: da läuft auch VMWare gleichzeitig mit drauf)


PS:
Magst du heute abend mal schauen was die Konsole bei dir anzeigt Fuel?
Anhang anzeigen TestProjekt.zip

Keine sorge, is kein Virus xD


----------



## Fu3L (13. Mrz 2012)

Schwankt auch bei mir zwischen 35 und 45 ms. Warum ist die erste Zeit eigentlich immer so kurz?

Hier mal das Sieb. Ich hoffe, dass das C++ und die Kommentare nicht zu grausig sind, ich kann C++ eigentlich gar nicht und es ist ein Jahr her^^ 


```
/*
 * Takes the pointer and points it onto a new array containing all primes in
 * the intervall [2;endNumber]
 *
 * returns the size of the array-1 (that is the last accessible index)
 *
 */

//Gets a reference to the pointer
int sievePrimes(int endNumber, long*& primes) {
	//If a field contains true it is crossed out
	int length = endNumber / 2;
	bool * sieve = new bool[length + 1];
	sieve[0] = true; //Represents 2
	double tmp = sqrt(endNumber / 2.);
	int sqrt = ceil(tmp);
	//1 -> 3; 2 -> 5; 3 -> 7 (saves all multiples of 2)
	for (int i = 1; i <= sqrt; i++) {
		//Not crossed out
		if (!sieve[i]) {
			long temp = i * 2 + 1;
			//Cross out all multiples of i starting at i²
			for (long n = 2 * i * (i + 1); n <= length; n += temp) {
				sieve[(int) n] = true;
			}
		}
	}

	//Fint out the size of the needed array
	int bound = 0;
	for(int i = 0; i <= length; i++) {
		if(!sieve[i]) {
			bound++;
		}
	}
	primes = new long[bound];
	//Reduce bound by 1 to use it as index when accessing the array
	bound--;
	int n = 1;
	primes[0] = 2;
	for(int i = 1; i <= length; i++) {
		if(!sieve[i]) {
			primes[n] = i*2+1;
			n++;
		}
	}
	delete [] sieve;
	return bound;
} //end sieving primes
```

Die Java Variante könnte den Vorteil oder Nachteil haben, dass ich TLongList nehme und daher nicht vorher nachzählen muss, wie groß das Array sein muss.


----------



## Gossi (13. Mrz 2012)

Fu3L hat gesagt.:


> ```
> int sievePrimes(int endNumber, long*& primes) {
> ```



Welchen wert muss den primes haben? ^^

Und warum die erste Zahl so kurz ist, keine Ahnung ^^


----------



## Fu3L (13. Mrz 2012)

Wenn ich das richtig in Erinnerung habe geht long * primes, das übergibst du dann der Methode sieve(1000000, primes) und die setzt da 'nen array rein^^ Ich mag Pointer und Referenzen nicht^^


----------



## Gossi (13. Mrz 2012)

Okay....

Hab übrigens mein Programm mal nen bisschen getestet:

```
Testsize: 1000
Zeit: 0ms
Testsize: 10000
Zeit: 0ms
Testsize: 100000
Zeit: 0ms
Testsize: 1000000
Zeit: 63ms
Testsize: 10000000
Zeit: 359ms
Testsize: 100000000
Zeit: 3344ms
Testsize: 1000000000
Zeit: 41906ms
Testsize: 1410065408
Zeit: 62188ms
Testsize: 1215752192
Zeit: 52453ms
```
Wird gegen ende doch recht langsam


----------



## Gast2 (13. Mrz 2012)

Da du ein Verfahren auf Basis der Probedivision angestellt hast ist das klar denn der Aufwand verält sich:


----------



## Gossi (14. Mrz 2012)

kappesf hat gesagt.:


> Da du ein Verfahren auf Basis der Probedivision angestellt hast ist das klar denn der Aufwand verält sich:



Das es langsamer wird, wusste ich, aber das er so lange braucht....

PS:

Die Zeit messe ich mit diesem Timer:

```
#include <sys/timeb.h>
#include "Timer.h"


Timer::Timer() {}

Timer::Timer(const Timer& a){}

Timer::~Timer(){}

void Timer::start( void ) {
    ftime( &mStart );
}

void Timer::stop( void ) {
    ftime( &mStop );
}

long Timer::getMilliseconds( void ) {
    return (long)(1000 * (mStop.time - mStart.time) + mStop.millitm - mStart.millitm);
}
```
Hab ich mal im Internet gefunden..


----------

