Darf der Compiler private Datenelemente optimieren?

Dec 08 2020

Wenn der Compiler nachweisen kann, dass ein (privates) Mitglied einer Klasse niemals verwendet wird, auch nicht von potenziellen Freunden, erlaubt der Standard dem Compiler, dieses Mitglied aus dem Speicherbedarf der Klasse zu entfernen?

Es versteht sich von selbst, dass dies für geschützte oder öffentliche Mitglieder zum Zeitpunkt der Kompilierung nicht möglich ist, aber es kann Umstände geben, unter denen es für private Datenmitglieder möglich ist, einen solchen Beweis zu erstellen.


Verwandte Fragen:

  • Hinter den Kulissen von öffentlich, privat und geschützt (löste diese Frage aus)
  • Darf der C ++ - Compiler nicht referenzierte lokale Objekte (über automatische Objekte) optimieren?
  • Wird eine statische Variable immer Speicher verbrauchen? (über statische Objekte)

Antworten

31 PeterCordes Dec 08 2020 at 23:19

Theoretisch möglich (zusammen mit nicht verwendeten öffentlichen Mitgliedern), aber nicht mit der Art von Compiler-Ökosystem, die wir gewohnt sind (auf einen festen ABI abzielen, der separat kompilierten Code verknüpfen kann). Das Entfernen nicht verwendeter Mitglieder konnte nur mit einer Gesamtprogrammoptimierung durchgeführt werden, die separate Bibliotheken verbietet 1 .

Andere Kompilierungseinheiten müssen sich möglicherweise einigen sizeof(foo), aber das wäre nichts, was Sie daraus ableiten könnten, .hwenn es darauf ankommt, zu überprüfen, ob keine Implementierung des Verhaltens einer Mitgliedsfunktion von privaten Mitgliedern abhängt.

Denken Sie daran, dass C ++ nur ein Programm angibt, keine Möglichkeit, Bibliotheken zu erstellen. Die von ISO C ++ angegebene Sprache ist (natürlich) mit dem von uns gewohnten Implementierungsstil kompatibel, aber Implementierungen, die alle .cppund .hDateien gleichzeitig aufnehmen und eine einzige in sich geschlossene, nicht erweiterbare ausführbare Datei erzeugen, sind möglich.

Wenn Sie die Implementierung ausreichend einschränken (kein fester ABI), wird eine aggressive Anwendung der Als-ob-Regel im gesamten Programm möglich.


Fußnote 1: Ich wollte "hinzufügen oder die Größeninformationen irgendwie in anderen zu kompilierenden Code exportieren ", um Bibliotheken zuzulassen, wenn der Compiler bereits Definitionen für jede in der Klasse deklarierte Mitgliedsfunktion sehen konnte. Die Antwort von @ PasserBy weist jedoch darauf hin, dass eine separat kompilierte Bibliothek die deklarierten privaten Mitglieder auf eine Weise verwenden könnte, die letztendlich von außen sichtbare Nebenwirkungen hervorruft (wie E / A). Wir müssten sie also vollständig ausschließen.

Angesichts dessen sind öffentliche und private Mitglieder für die Zwecke einer solchen Optimierung gleichwertig.

17 KonradRudolph Dec 08 2020 at 22:26

Wenn der Compiler nachweisen kann, dass ein (privates) Mitglied einer Klasse niemals verwendet wird

Der Compiler kann nicht beweisen , dass, weil private Mitglieder können in anderen Übersetzungseinheiten verwendet werden. Konkret ist dies im Zusammenhang mit einem Zeiger auf ein Mitglied in einem Vorlagenargument gemäß [temp.spec] / 6 des Standards möglich, wie ursprünglich von Johannes Schaub beschrieben .

Zusammenfassend: Nein, der Compiler darf private Datenelemente nicht mehr als öffentliche oder geschützte Mitglieder optimieren (vorbehaltlich der Als-ob-Regel).

11 PasserBy Dec 08 2020 at 22:30

Nein, da Sie das Zugangskontrollsystem legal untergraben können .

class A
{
    int x;
};

auto f();

template<auto x>
struct cheat
{
    friend auto f() { return x; }
};

template struct cheat<&A::x>;  // see [temp.spec]/6

int& foo(A& a)
{
    return a.*f();  // returns a.x
}

Da der Compiler das ABI bei der Aersten Verwendung reparieren muss und nie wissen kann, ob zukünftiger Code darauf zugreifen kann x, muss er den Speicher von Aenthalten , um ihn zu enthalten x.