Ich war mir immer unsicher, was das Restriktionsschlüsselwort in C ++ bedeutet.
Bedeutet dies, dass sich die zwei oder mehr Zeiger, die der Funktion zugewiesen wurden, nicht überlappen? Was bedeutet es sonst noch?
c++
restrict-qualifier
Matte
quelle
quelle
restrict
ist ein c99-Schlüsselwort. Ja, Rpbert S. Barnes, ich weiß, dass die meisten Compiler dies unterstützen__restrict__
. Sie werden feststellen, dass alles mit doppelten Unterstrichen per Definition implementierungsspezifisch und somit NICHT C ++ ist , sondern eine compilerspezifische Version davon.#warning
Anweisung oder die Funktionssignaturmakros (__PRETTY_FUNCTION__
in GCC,__FUNCSIG__
in MSVC usw.).restrict
wird nicht als C ++ - Schlüsselwort betrachtet (siehe en.cppreference.com/w/cpp/keyword ) und ist die einzige Erwähnungrestrict
im C ++ 11-Standard (siehe open-std.org/jtc1/sc22/wg21) /docs/papers/2012/n3337.pdf , eine Kopie des FDIS mit geringfügigen redaktionellen Änderungen, §17.2 [library.c], PDF-Seite 413) besagt:restrict
werden soll , von weggelassen (ausgenommen von links aus) C - Standardbibliothek Funktionssignaturen und Semantik , wenn diese Funktionen in der C ++ Standardbibliothek enthalten sind. Mit anderen Worten, ich habe die Tatsache angegeben, dassrestrict
dasrestrict
Schlüsselwort aus der Signatur des C ++ - Äquivalents entfernt werden muss , wenn die Signatur einer C-Standardbibliotheksfunktion in C enthalten ist .Antworten:
In seinem Artikel Memory Optimization sagt Christer Ericson, dass er zwar
restrict
noch nicht Teil des C ++ - Standards ist, aber von vielen Compilern unterstützt wird, und er empfiehlt, ihn zu verwenden, wenn er verfügbar ist:In C ++ - Compilern, die dies unterstützen, sollte es sich wahrscheinlich genauso verhalten wie in C.
Weitere Informationen finden Sie in diesem SO-Beitrag: Realistische Verwendung des C99-Schlüsselworts "einschränken"?
Nehmen Sie sich eine halbe Stunde Zeit, um Ericsons Zeitung zu lesen. Es ist interessant und die Zeit wert.
Bearbeiten
Ich fand auch heraus, dass der AIX C / C ++ - Compiler von
__restrict__
IBM das Schlüsselwort unterstützt .g ++ scheint dies ebenfalls zu unterstützen, da das folgende Programm unter g ++ sauber kompiliert wird:
Ich habe auch einen schönen Artikel über die Verwendung von gefunden
restrict
:Das Restrict-Schlüsselwort entmystifizieren
Edit2
Ich bin auf einen Artikel gestoßen, in dem speziell die Verwendung von Restrict in C ++ - Programmen beschrieben wird:
Load-Hit-Stores und das Schlüsselwort __restrict
Microsoft Visual C ++ unterstützt auch das
__restrict
Schlüsselwort .quelle
#ifndef __GNUC__
#define __restrict__ /* no-op */
oder ähnliches tun . Und definieren Sie es,__restrict
wenn_MSC_VER
definiert ist.Wie andere sagten, wenn ab C ++ 14 nichts bedeutet , betrachten wir die
__restrict__
GCC-Erweiterung, die dasselbe tut wie die C99restrict
.C99
restrict
sagt, dass zwei Zeiger nicht auf überlappende Speicherbereiche zeigen können. Die häufigste Verwendung sind Funktionsargumente.Dies schränkt den Aufruf der Funktion ein, ermöglicht jedoch weitere Kompilierungsoptimierungen.
Wenn der Anrufer dem
restrict
Vertrag nicht folgt , undefiniertes Verhalten.Der C99 N1256 Entwurf 6.7.3 / 7 "Typqualifizierer" sagt:
und 6.7.3.1 "Formale Definition von Beschränkung" gibt die blutigen Details an.
Eine mögliche Optimierung
Das Wikipedia-Beispiel ist sehr aufschlussreich.
Es zeigt deutlich, wie eine Montageanweisung gespeichert werden kann .
Ohne Einschränkung:
Pseudo-Assemblierung:
Mit Einschränkung:
Pseudo-Assemblierung:
Macht GCC das wirklich?
g++
4.8 Linux x86-64:Mit
-O0
sind sie gleich.Mit
-O3
:Für die Uneingeweihten lautet die aufrufende Konvention :
rdi
= erster Parameterrsi
= zweiter Parameterrdx
= dritter ParameterDie GCC-Ausgabe war noch deutlicher als der Wiki-Artikel: 4 Anweisungen gegen 3 Anweisungen.
Arrays
Bisher haben wir Einsparungen bei einzelnen Anweisungen, aber wenn Zeiger Arrays darstellen, die durchlaufen werden sollen, ein häufiger Anwendungsfall, dann könnte eine Reihe von Anweisungen gespeichert werden, wie von Supercat und Michael erwähnt .
Betrachten Sie zum Beispiel:
Wegen
restrict
, ein Smart - Compiler (oder Menschen), könnten diese optimieren:Was ist möglicherweise viel effizienter, da es für eine anständige libc-Implementierung (wie glibc) Assembly-optimiert werden kann ? Ist es in Bezug auf die Leistung besser, std :: memcpy () oder std :: copy () zu verwenden? , möglicherweise mit SIMD-Anweisungen .
Ohne Einschränkung könnte diese Optimierung nicht durchgeführt werden, z. B. berücksichtigen Sie:
Dann
for
macht die Version:während die
memset
Version macht:Macht GCC das wirklich?
GCC 5.2.1.Linux x86-64 Ubuntu 15.10:
Mit
-O0
sind beide gleich.Mit
-O3
:mit einschränken:
Zwei
memset
Anrufe wie erwartet.ohne Einschränkung: keine stdlib-Aufrufe, nur eine 16 Iterationen breite Schleife, die ich hier nicht reproduzieren möchte :-)
Ich hatte nicht die Geduld, sie zu vergleichen, aber ich glaube, dass die eingeschränkte Version schneller sein wird.
Strikte Aliasing-Regel
Das
restrict
Schlüsselwort wirkt sich nur auf Zeiger kompatibler Typen aus (z. B. zweiint*
), da die strengen Aliasing-Regeln besagen, dass das Aliasing inkompatibler Typen standardmäßig ein undefiniertes Verhalten ist. Compiler können daher davon ausgehen, dass dies nicht der Fall ist, und optimieren.Siehe: Was ist die strenge Aliasing-Regel?
Funktioniert es für Referenzen?
Laut den GCC-Dokumenten gilt Folgendes: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html mit Syntax:
Es gibt sogar eine Version für
this
Mitgliedsfunktionen:quelle
-fno-strict-aliasing
,restrict
sollte es keinen Unterschied zwischen Zeigern desselben Typs oder verschiedener Typen machen, nein? (Ich beziehe mich auf "Das Schlüsselwort einschränken betrifft nur Zeiger kompatibler Typen")restrict
bedeutet etwas in C ++. Wenn Sie eine C-Bibliotheksfunktion mitrestrict
Parametern aus einem C ++ - Programm aufrufen , müssen Sie deren Auswirkungen berücksichtigen. Wennrestrict
es in einer C-Bibliotheks-API verwendet wird, bedeutet dies für jeden, der es aus einer beliebigen Sprache aufruft, einschließlich des dynamischen FFI von Lisp.Nichts. Es wurde dem C99-Standard hinzugefügt.
quelle
restrict
Schlüsselwort. Daher steht meine Antwort richtig. Was Sie beschreiben, ist implementierungsspezifisches Verhalten und etwas, auf das Sie sich nicht wirklich verlassen sollten.Dies ist der ursprüngliche Vorschlag, dieses Schlüsselwort hinzuzufügen. Wie direkt gesagt, handelt es sich hierbei um eine C99- Funktion. es hat nichts mit C ++ zu tun.
quelle
__restrict__
Schlüsselwort, das meines Erachtens identisch ist.restrict
. Das Verhalten des C ++ - Programms wird undefiniert, wenn es die durch implizierten Einschränkungen verletztrestrict
.restrict
Schlüsselwort entfernen . Wenn Sie Alias-Zeiger an eine C-Funktion übergeben, die sie als eingeschränkt deklariert (was Sie entweder mit C ++ oder C tun können), ist dies natürlich undefiniert, aber das liegt an Ihnen.restrict
. Das Verhalten des C ++ - Programms wird undefiniert, wenn es die durch Einschränken implizierten Einschränkungen verletzt. Aber das hat eigentlich nichts mit C ++ zu tun, weil es "auf dir" liegt.In C ++ gibt es kein solches Schlüsselwort. Eine Liste der C ++ - Schlüsselwörter finden Sie in Abschnitt 2.11 / 1 des C ++ - Sprachstandards.
restrict
ist ein Schlüsselwort in der C99-Version der C-Sprache und nicht in C ++.quelle
__restrict__
Schlüsselwort, das meines Erachtens identisch ist.Da Header-Dateien aus einigen C-Bibliotheken das Schlüsselwort verwenden, muss die C ++ - Sprache zumindest etwas dagegen tun. Dabei wird das Schlüsselwort ignoriert, sodass das Schlüsselwort nicht in einem leeren Makro definiert werden muss, um das Schlüsselwort zu unterdrücken .
quelle
extern C
Deklaration oder durch stillschweigendes Löschen behandelt wird, wie dies beim AIX C / C ++ - Compiler der Fall ist, der stattdessen das__rerstrict__
Schlüsselwort verarbeitet. Dieses Schlüsselwort wird auch unter gcc unterstützt, sodass der Code unter g ++ dasselbe kompiliert.