C ++ 17 inline
Variablen
Mit dieser fantastischen C ++ 17-Funktion können wir:
- Verwenden Sie bequemerweise nur eine einzige Speicheradresse für jede Konstante
- Speichern Sie es als
constexpr
: Wie deklariere ich constexpr extern?
- Machen Sie es in einer einzigen Zeile aus einem Header
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
Kompilieren und ausführen:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub stromaufwärts .
Siehe auch: Wie funktionieren Inline-Variablen?
C ++ - Standard für Inline-Variablen
Der C ++ - Standard garantiert, dass die Adressen gleich sind. C ++ 17 N4659 Standardentwurf
10.1.6 "Der Inline-Spezifizierer":
6 Eine Inline-Funktion oder Variable mit externer Verknüpfung muss in allen Übersetzungseinheiten dieselbe Adresse haben.
cppreference https://en.cppreference.com/w/cpp/language/inline erklärt, dass, wenn static
nicht angegeben, eine externe Verknüpfung besteht.
Inline-Variablenimplementierung
Wir können beobachten, wie es implementiert wird mit:
nm main.o notmain.o
was beinhaltet:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
und man nm
sagt über u
:
"u" Das Symbol ist ein eindeutiges globales Symbol. Dies ist eine GNU-Erweiterung des Standardsatzes von ELF-Symbolbindungen. Für ein solches Symbol stellt der dynamische Linker sicher, dass im gesamten Prozess nur ein Symbol mit diesem Namen und Typ verwendet wird.
Wir sehen also, dass es dafür eine dedizierte ELF-Erweiterung gibt.
C ++ 17 Standardentwurf zu "global" const
impliziertstatic
Dies ist das Zitat für das, was unter https://stackoverflow.com/a/12043198/895245 erwähnt wurde
C ++ 17 n4659 Standardentwurf 6.5 "Programm und Verknüpfung":
3 Ein Name mit Namespace-Bereich (6.3.6) hat eine interne Verknüpfung, wenn es sich um den Namen von handelt
- (3.1) - eine Variable, Funktion oder Funktionsvorlage, die explizit als statisch deklariert ist; oder,
- (3.2) - eine nicht inline Variable vom nichtflüchtigen const-qualifizierten Typ, die weder explizit als extern deklariert noch zuvor als extern verknüpft deklariert wurde; oder
- (3.3) - ein Datenmitglied einer anonymen Gewerkschaft.
Der Bereich "Namespace" wird umgangssprachlich häufig als "global" bezeichnet.
Anhang C (informativ) Kompatibilität, C.1.2 Abschnitt 6: "Grundbegriffe" begründet, warum dies von C geändert wurde:
6.5 [auch 10.1.7]
Änderung: Ein Name des Dateibereichs, der explizit als const deklariert und nicht explizit als extern deklariert wird, hat eine interne Verknüpfung, während er in C eine externe Verknüpfung hätte.
Begründung: Da const-Objekte während der Übersetzung in C ++ als Werte verwendet werden können, fordert diese Funktion Programmierer auf, für jedes const-Objekt einen expliziten Initialisierer bereitzustellen. Mit dieser Funktion kann der Benutzer const-Objekte in Quelldateien einfügen, die in mehr als einer Übersetzungseinheit enthalten sind.
Auswirkung auf das ursprüngliche Merkmal: Wechseln Sie zur Semantik eines genau definierten Merkmals.
Schwierigkeiten beim Konvertieren: Semantische Transformation.
Wie weit verbreitet: Selten.
Siehe auch: Warum impliziert const eine interne Verknüpfung in C ++, wenn dies in C nicht der Fall ist?
Getestet in GCC 7.4.0, Ubuntu 18.04.
const int
? Beispielcode posten, der nicht kompiliert werden konnte, wenn das Ihre Frage ist?