Il compilatore è autorizzato a ottimizzare i membri di dati privati?

Dec 08 2020

Se il compilatore può provare che un membro (privato) di una classe non viene mai utilizzato, inclusi potenziali amici, lo standard consente al compilatore di rimuovere questo membro dall'impronta di memoria della classe?

È ovvio che ciò non è possibile per i membri protetti o pubblici al momento della compilazione, ma potrebbero esserci circostanze in cui è possibile per quanto riguarda i membri di dati privati ​​costruire tale prova.


Domande correlate:

  • Dietro le quinte di pubblico, privato e protetto (ha suscitato questa domanda)
  • Il compilatore C ++ è autorizzato a ottimizzare gli oggetti locali non referenziati (sugli oggetti automatici)
  • Una variabile statica utilizzerà sempre la memoria? (sugli oggetti statici)

Risposte

31 PeterCordes Dec 08 2020 at 23:19

Possibile in teoria (insieme a membri pubblici inutilizzati), ma non con il tipo di ecosistema di compilatori a cui siamo abituati (mirato a un ABI fisso che può collegare codice compilato separatamente). La rimozione dei membri inutilizzati può essere eseguita solo con l'ottimizzazione dell'intero programma che proibisce le librerie separate 1 .

Potrebbe essere necessario concordare altre unità di compilazione sizeof(foo), ma non sarebbe qualcosa da cui potresti derivare .hse dipendesse dalla verifica che nessuna implementazione del comportamento di una funzione membro dipenda da membri privati.

Ricorda che C ++ specifica solo un programma, non un modo per creare le librerie. Il linguaggio ISO C ++ specifica è compatibile con lo stile di esecuzione a cui siamo abituati (ovviamente), ma le implementazioni che prendono tutte le .cppe .hfile contemporaneamente e produrre un unico file eseguibile non estensibile autonomo sono possibili.

Se si limita abbastanza l'implementazione (nessun ABI fisso), diventa possibile un'applicazione aggressiva dell'intero programma della regola as-if.


Nota 1: stavo per aggiungere " o esportare le informazioni sulla dimensione in qualche modo in altro codice da compilare " come un modo per consentire le librerie, se il compilatore poteva già vedere le definizioni per ogni funzione membro dichiarata nella classe. Ma la risposta di @ PasserBy sottolinea che una libreria compilata separatamente potrebbe essere l'elemento che utilizza i membri privati ​​dichiarati in modi che alla fine producono effetti collaterali visibili esternamente (come I / O). Quindi dovremmo escluderli completamente.

Detto questo, i membri pubblici e privati ​​sono equivalenti ai fini di tale ottimizzazione.

17 KonradRudolph Dec 08 2020 at 22:26

Se il compilatore può provare che un membro (privato) di una classe non viene mai utilizzato

Il compilatore non può provarlo, perché i membri privati possono essere utilizzati in altre unità di compilazione. In concreto, ciò è possibile nel contesto di un puntatore a un membro in un argomento modello secondo [temp.spec] / 6 dello standard, come originariamente descritto da Johannes Schaub .

Quindi, in sintesi: no, il compilatore non deve ottimizzare i membri di dati privati ​​più dei membri pubblici o protetti (soggetti alla regola as-if).

11 PasserBy Dec 08 2020 at 22:30

No, perché puoi sovvertire legalmente il sistema di controllo degli accessi .

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
}

Dato che il compilatore deve correggere l'ABI quando Aviene utilizzato per la prima volta e che non può mai sapere se un codice futuro potrebbe accedere x, deve correggere la memoria Ada contenere x.