F
@Yadgar sagte in Fehlermeldung bei globalem vector-Objekt vom Typ string:
#include <string.h>
#include <vector>
...
vector<string> errormsgs; // Liste der Fehlermeldungen
errormsgs.push_back("Befehl unbekannt!"); // in parse()
Gleich vorweg: Du möchtest wahrscheinlich #include <string> und nicht #include <string.h> verwenden. Ersteres holt std::string herein, letzteres ist für C String-Functionen wie strcpy und so'n Kram. Wenn das bei dir nicht zu einem Fehler geführt hat, dann ist das purer Zufall, z.B. weil ein anderer Header std::string für dich eingebunden hat.
Zu deinem Problem: Du kannst keine "Statements" zwischen den Funktionen schreiben, nur Deklarationen, Definitionen und Variablen-Initialisierungen. Wenn du möchtest, dass errmsgs einen Default-Eintrag bekommt, dann muss du den in einer Initialisierung erzeugen. z.B. so:
// Liste der Fehlermeldungen
vector<string> errormsgs = { "Befehl unbekannt!" };
Das ist m.E. die sauberste Form für so einen simplen Default-Eintrag. Für komplizierteres kann man auch mithilfe einer Lambda-Funktion initalisieren. Damit kommt man darum herum, dass man nicht einfach "zwischen die Funktionen" irgendwelche v.push_back()-Funtkionen aufrufen kann:
// Liste der Fehlermeldungen
vector<string> errormsgs = []{
vector<string> init;
init.push_back("Befehl unbekannt!");
return init;
}();
Info: Das "()" am Ende ist wichtig, damit wird nämlich die Lambda-Funktion direkt aufgerufen und der vector mit dem Rückgabenwert initialisiert (Copy-Konstruktion). Merke: das ist immer noch eine Initialisierung, man kann da durchaus Funktionen in dieser Form aufrufen, nur nackte Funktionsaufrufe ohne Initialisierung sind nicht erlaubt.
Alternativ geht auch so was (ich finde das mit der Lambda-Funktion allerdings eleganter, weil es alles kompakt zusammenhält):
auto init_errormsgs()
{
vector<string> init;
init.push_back("Befehl unbekannt!");
return init;
}
vector<string> errormsgs = init_errormsgs();
Ansonsten: Wenn du nicht unbedingt dynamische Strings benötist, kannst du für solche Fehlermeldungen auch statische Strings verwenden. Eine moderne C++-Variante wäre z.B. diese hier:
#include <vector>
#include <string_view>
using namespace std;
// Liste der Fehlermeldungen
vector<string_view> errormsgs = { "Befehl unbekannt!" };
Das kann man so machen, weil solche String-Literale direkt in das Programm eingebettet werden und char*-Pointer auf diese für die gesamte Laufzeit des Programms gültig bleiben. Das ist auch insofern effizienter, da in dieser Form der Compiler den vector direkt in der .data-Section des Programms anlegen kann und dieser dann nicht bei der Programminitialisierung konstruiert werden muss (etwas weniger Arbeit und kompakter in der Executable). Für dynamische Strings erzeugt der Compiler nämlich einen versteckten "Global Constructor", der dann beim Start des Programms automatisch vor main() aufgerufen wird, und der vielleicht so aussehen könnte:
void __GLOBAL_construct_errormsgs()
{
errormsgs.push_back("Befehl unbekannt!")
}
Ein statisches Objekt hingegen, wie der string_view-Vektor würde stattdessen direkt fertig konstruiert geladen und benötigt eine solche Funktion nicht. Das ist nur ein relativ nebesächliches Detail, aber vielleicht ganz interessant zu wissen (das ist mir nur gerade sehr präsent, weil ich in meinem derzeitigen Hobbyprojekt um jedes Byte in der Binary kämpfe ).