Re: Rückgabe von mehrdimensionalem String in C++

Konrad Rosenbaum <[email protected]>
Newsgroups gmane.user-groups.linux.dresden
Message-ID <[email protected]>
Hi,


On 02/05/2022 21:58, Jeffrey Kelling wrote:
>> make
>>
>> g++    -c -o src/lib/init_hw.o src/lib/init_hw.cpp
>> src/lib/init_hw.cpp:In member function ‘void ZEROHW::init_hw(const
>> std::vector<std::__cxx11::basic_string<char> >&)’:
>> src/lib/init_hw.cpp:52:69:error: use of ‘auto
>> READCSV::read_config_files(const string&)’ before deduction of ‘auto’
>>     52 |             auto pin_defs =
>> read_csv.read_config_files(file_names[0]);
>>        | ^
>> make: *** [<eingebaut>: src/lib/init_hw.o] Fehler 1
> Hast du vllt die Funktion mit `auto` Rückgabetyp in einem Header nur
> deklariert, aber nicht definiert? `auto` geht nur, wenn der Compiler beim
> Aufruf auch sieht was in der Funktion zurückgegeben wird, wenn sie als auf
> irgendeineweise inline bzw. in der gleichen Kompiliereinheit definiert wird.
> Wenn die Definition in einer separaten Einiheit ist, dann musst du explizit
> sagen was der Rückgabetyp ist, also `std::vector<csv_values>`.


Noch ein kleiner Nachschlag dazu: auto ist eines der praktischsten 
Features in C++-11, aber wie immer in C++ kann/sollte man es nicht immer 
und überall einsetzen.


Wann man auto unbedingt einsetzen sollte:

Wenn man einen numerischen Typ von einer Funktion zurückbekommt: auto 
zahl = meineFunktion();
Das verhindert dass man den falschen Typ für "zahl" deklariert und ein 
automatischer Cast den Wertebereich kaputt macht (beliebt sind "int" und 
"sizeof" auf 64-bit Maschinen).

Als Rückgabetyp wenn man Templates definiert (Profi-Tip: wenn Du 
innerhalb der ersten 5 Jahre C++ ein Template definierst, dann machst Du 
wahrscheinlich was falsch; Templates benutzen ist dagegen okay, 
gewünscht und sogar hilfreich).

Bei komplexen Operationen bei denen es nicht intuitiv ist was der 
Ergebnistyp ist: auto ergebnis = 
getMyCollection().at(42).transform(otherGadget).last();


Wan man NICHT auto einsetzen sollte:

Wenn man selbst Funktionen/Methoden deklariert, es sei denn es ist eine 
triviale inline-Funktion. Also alles was komplexer als "inline auto 
square(int a){return a*a;}" ist sollte seinen Typ explizit deklarieren. 
Sprich: wenn die Definition der Funktion inline im Header steht und auf 
eine Zeile passt, dann auto, sonst explizit.

Wenn man weiß dass mit Referenzen oder Pointern herumhantiert wird und 
man den Wert weitergeben oder aufheben will, dann ist es einfacher 
explizit zu sagen welcher nicht-Referenz-Typ es sein soll.

In der Parameterliste von Funktionen bringt es nur unverständliche 
Fehlermeldungen. ;-)

Vorsicht bei der Initialisierung von Member-Variablen: auto mysize=5; 
ist wahrscheinlich nicht so gewollt - es erzeugt eine int Variable, aber 
"size" sollte lieber size_t, ssize_t oder long sein...


Für alle anderen Fälle gilt:

Wenn eine Ergebnis-Variable auto-Typing bekommt hilft es im Allgemeinen 
Verwirrung zu vermeiden, aber es gibt Ausnahmen.



Wo wir gerade bei Vereinfachungen und Hinweisen sind:

  * deklariere so viel wie möglich const - dann sagt Dir der Compiler
    wenn Du ausversehen irgendwo schreibst wo Du es nicht solltest, z.B.
    if(a=3)...
  * bei großen Datentypen (string, array, vector, ...): deklariere
    Funktionsparameter als const-Referenz (geht schneller),
    Rückgabe-Typen als non-Referenz (crasht sonst gerne mal); merke Dir
    niemals eine Referenz, sondern mach' Kopien
  * wenn Du schon Pointer benutzt, dann initialisiere sie auf nullptr
    und setze sie nach delete auch immer auf nullptr zurück - das macht
    die Fehlerdiagnose einfacher!
  * wenn Du eine Referenz zurückgibst machst Du zu 99% einen Fehler, das
    verbleibende 1% ist zum größten Teil schon von der STL abgedeckt
  * Pointer sind Teufelswerk; Referenzen sind besser aber nicht ganz
    ungefährlich(*); Value-Typen sind fett und langsam - wähle Dein Gift
    vorsichtig ;-)
  * Optimiere erst wenn Du merkst dass es nötig ist, nicht schon wenn Du
    glaubst cleverer zu sein als Dein Computer (moderne Compiler sind
    Wunderwerke der Technik)
  * C-Strings sind okay um std::string zu initialisieren (z.B.
    std::string s="Hallo Welt"), aber sonst sollten sie vermieden werden.
  * Kommentare sind gesund, erhöhen die Biodiversität im Code-Dschungel
    und sollten gut gepflegt werden. Fehlende Kommentare führen zu
    tragischen Code-Verlusten.

(*)Apropos Referenzen:

  * Referenzen auf globale Variablen sind okay, aber eigentlich sollte
    man globale Werte vermeiden
  * Referenzen auf statische Klassen-Variablen sind okay und besser als
    ganz globale Werte
  * Referenzen auf Variablen in main() sind meistens okay, können aber
    schiefgehen wenn sie in im Exit-Handler benutzt werden (z.B. im
    Destruktor einer globalen Variable, ja der wird aufgerufen!)
  * Referenzen auf lokale Werte sollte man vermeiden - es ist okay sie
    in einen tieferen Stack-Frame zu geben, solange der sich die
    Referenz nicht merkt
  * Referenzen auf Werte aus einem tieferen Stack-Frame sind
    lebensgefährlich, weil der Speicher entweder schon freigegeben ist
    oder Unsinn enthält
  * Referenzen, die von einer Funktion zurückgegeben werden sollte man
    nur auf der selben Zeile verwenden und dann vergessen, wenn Du es
    länger brauchst mach eine Kopie
  * Nimm niemals an dass eine Referenz aus einem Parameter länger lebt
    als die aktuelle Funktion!



     Konrad
OpenPGP_signature (application/pgp-signature, 495 B) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.