Nachdem dieser Thread nur noch aus Meldungen über mehr oder weniger neue C++ Featuers besteht, habe ich den Titel entsprechend angepaßt.
Zur ursprünglichen Frage: Wieviel C++ verträgt ein kleiner Arduino?
Bitte jetzt nicht mit "so viel wie möglich" antworten, mir geht es um die kleinen Dinge(r) mit wenig RAM. Dort sollte man z.B. keinen String verwenden, oder ganz allgemein keine dynamischen Objekte.
Was bleibt dann von C++ noch übrig, das sich gefahrlos benutzen läßt? Gehört die STL dazu?
Sie müssen also wahrscheinlich qualifizieren, was ein Arduino ist oder was wenig RAM ist (mein Mac hat 32 Go 2667 MHz DDR4, also würde mir alles unter 1 Go klein erscheinen)
UNO?
MKR ?
nicht arduino (ESP32)?
String ist nicht ganz unbedenklich.
Ist aber problemlos nutzbar, wenn man sich leichten/freiwilligen Beschränkungen unterwirft.
Das gilt für jegliche dynamische Speicherreservierung.
Größere Prozessoren lindern die Probleme nur.
Aber schaffen sie nicht aus der Welt.
Vereinfacht:
Je Kleiner der µC, desto mehr Disziplin, ist wohl nötig.
In manchen Fällen ist notwendig Speicher dynamisch zu reservieren.
Es gibt also nicht wirklich nur ein gut und böse.
Als in den 80er Jahren (des vorigen Jahrhunderts ) C seinen Siegeszug begann und später C++ auch objektorientierte Programmierung ermöglichte, war klar dass es eine Super-Sache ist, selbst für kleinste Controller diese Sprache zur Verfügung zu haben, um nicht in einer prozessorabhängigen Assemblersprache rumfummeln zu müssen.
Wie immer, nimmt einem ein Werkzeug nicht die Arbeit ab, sondern erleichtert sie oder ermöglicht Dinge, die ohne das Werkzeug gar nicht möglich wären.
Teil der Arbeit ist, die physikalischen Gegebenheiten im Blick zu halten.
Nicht umsonst ist in C nicht mal die Größe eines int festgelegt.
Und C++ ist dieselbe Sprache, egal welche Bibliothek in welcher Implementierung für den gewählten Compiler zur Verfügung steht.
Wie groß muss eine Ganzzahl-Variable sein, wenn man damit die Anzahl der Elektronen im beobachtbaren Universum zählen will? Und was kann ich mit einem uint8_t machen?
Sehr schön, danke.
Wobei die Frage bleibt, ob ein Problem, das erst später zum Tragen kommt, weniger schwer ist?
Die Beschränkungen ergeben sich aus dem Verhalten der String Klasse.
Also erstmal das, was die Stingklasse böse macht:
Viele global definierte Stringobjekte sind ein Problem, da sie den Speicher/Head fragmentieren können.
Mildern kann man das mit String::reserve().
Was aber auch nur geht, wenn man die maximale Größe schon vorher bestimmen kann.
Von mir Empfohlene Beschränkung:
Nur eine globale Instanz nutzen
String::reserve() nutzen.
Gegen lokale Strings ist nichts einzuwenden(außer der Speicherverbrauch), denn die Klasse folgt dem RAII Pattern.
dynamische Zuweisung kann ohne Benachrichtigung fehlschlagen ... Sie können also nicht sicher sein, ob das Ergebnis einer solchen Verkettung oder einer substring-Extraktion funktioniert hat ...
der Autor hat gute Empfehlungen, und sie sind dokumentiert
Guidelines for Using Arduino Strings
Do not use the String + operator at all, C/C++ makes it is easy to get the code wrong. Avoid using the String(...) constructors as these create short lived temporary Strings. Use = and += operators or concat( ), as in result += “str”; result += 'c'; result += number; etc. See Minimizing Memory Usage
Declare long lived Strings as globals and reserve( ) space in setup() , starting with the smallest to the largest. Check the return from the last largest reserve( ) to see that you have enough memory for all the Strings
If you have created Strings in the loop() method, they are long lived, move them to Globals and repeat step 1.
Pass all Strings arguments to methods, as const String& . For results pass a String& result, that the method can update with the result. i.e. void strProcessing(const String &input1, const String &input2, ,, String &result) {..} See Using String& for arguments
Set the IDE File → Preferences Compiler Warning to ALL and watch for warning: passing 'const String' as 'this' argument discards qualifiers [-fpermissive] messages in the compile window. This says you are trying to modify a const String& arg.
Do string processing in small compact methods. In these methods use local Strings in preference to local char[]. These methods will completely recover all the heap and stack used by their local Strings and other variables on exit. See String versus char[]
To monitor for Low Memory and fragmentation, add a StringReserveCheck to at least the last largest String reserve( ). Add StringReserveCheck to other Strings as necessary. See Using StringReserveCheck (download and install StringReserveCheck.zip)
If your Arduino program uses the Web e.g. ESP32 / EPS8266 webserver/httpClient, then the underlying web support libraries already use lots of Strings. If you project is suppose to run for a long time, add a periodic automatic reboot. See ESP32/ESP8266 Adding Periodic Automatic Reboots
Don't call String methods from within an interrupt routine. String uses malloc/realloc to get memory from the heap to store the chars. malloc/realloc on the UNO, Mega2560 etc (AVR processors and others) are not designed to called from the main loop and then interrupted and called again (a reentrant call). The result is a crash due to malloc/realloc loosing track of what is happening unless you add extra 'guard' code to prevent it.
Mir fehlt da das größte Problem, die unsichtbare Verwendung von Strings in Operatoren, Funktionen und Methoden.
Mir hat von Anfang an so was gefehlt wie:
Serial << "Hello" << ' ' << Name << EOL;
Heute würde ich mich nicht mehr trauen, solche Operatoren zu benutzen, da ich deren Implementierung nicht kenne. Aber wer kennt die schon so genau, daß er zuverlässig vorhersagen kann, wann und wann nicht mit dynamischen Speicherproblemen zu rechnen ist?
Und in Anbetracht der stets länglichen Diskussionen und Tutorials über Strings kann man doch keinem Newbee empfehlen, String zu verwenden - die haben schon mit genug anderen Problemen zu kämpfen.
Naja. das Konstrukt ist doch recht normales C++
Und String kommt da gar nicht vor.
Hmmm....
Keine Ahnung welche Sorgen dich da plagen.....
Sage mir deine Bedenken, und ich werde mir Mühe geben, da etwas Klarheit zu bringen.
Es gibt nur wenige Operatoren(?) welche was mit dynamischer Speicherverwaltung zu tu haben. z.B. new und delete
Wenn man den Gedanken konsequent zu ende denkt, darf man überhaupt kein Sprachmittel empfehlen, da man mit wirklich jedem irgendwelche Perversitäten anstellen kann.
Sich ins eigene Knie schießen.
Am Rande:
Wenn irgendwer sagt: GOTO verwende ich nicht!
Oder ich sage: Lokale statische Variablen sind so böse, dass ich sie unbedingt vermeiden will.
Dann betrifft mich das, oder/und den anderen.
Aber die ganzen anderen lernenden User betrifft das nicht unmittelbar.
Sie können sich das zu eigen machen oder ablehnen.
Das ist eine freie Entscheidung.
Wie wäre es mit '+', um nur mal einen einfachen und vermutlich einfach verständlichen Operator zu nennen. Und wenn der dann in Verbindung mit String-Argumenten in einer Funktion auftaucht, wem fällt das sofort auf?
Mir?
Ok, sicherlich nicht immer sofort.
Aber wenn ich das selber schreibe, dann sicherlich schon.
Was ist die Alternative?
Auf + ganz verzichten
Keine eigenen + definieren
Das kann es doch beides nicht sein.
ApfelsinenKiste kiste;
int anzahl = 7;
kiste += anzahl ;
Wenn man sich klar macht, das + das zusammenfügen von Dingen bedeuten soll. Dann macht es doch in der Vorstellung kein Problem mehr, ob da 2 int addiert, oder 2 Zeichenketten verbunden werden. Oder eben Apfelsinen in eine Kiste geworfen werden.
Es ist ein Freiheitsgrad im Denken.
Damit auch im Handeln/Programmieren.
Es bleibt jedem selber überlassen, wie er mit diesen Freiheiten umgeht.
Man muß schon ein ganzes Stück tiefer buddeln um herauszubekommen, was bei numerischen Variablen passiert.
Und wenn das wirklich so harmlos wäre, warum empfiehlt man nicht gleich die Verwendung von "<<" für Ausgaben? Oder funktioniert das vielleicht garnicht mit Serial?
ganz verstehe ich deinen Frage nicht was du wirklich hören willst. Mir scheint der limitierende Faktor ist eher der Mensch der Code für "kleine" AVR schreibst. "String" lässt sich verwenden, dynamsiche Objekte auch - wenn man den Speicher im Blick hält, oder? Ist es nicht einfach so, dass alles geht, was mit den knappen Resourcen machbar ist? Also im Prinzip doch wieder "so viel wie möglich".