O compilador tem permissão para otimizar os membros de dados privados?

Dec 08 2020

Se o compilador puder provar que um membro (privado) de uma classe nunca é usado, incluindo por amigos em potencial, o padrão permite que o compilador remova esse membro da área de cobertura da memória da classe?

É evidente que isso não é possível para membros protegidos ou públicos no momento da compilação, mas pode haver circunstâncias em que é possível, em relação aos membros de dados privados, que tal prova seja construída.


Perguntas relacionadas:

  • Nos bastidores do público, privado e protegido (gerou esta questão)
  • O compilador C ++ tem permissão para otimizar objetos locais não referenciados (sobre objetos automáticos)
  • Uma variável estática sempre usará memória? (sobre objetos estáticos)

Respostas

31 PeterCordes Dec 08 2020 at 23:19

Possível em teoria (junto com membros públicos não utilizados), mas não com o tipo de ecossistema de compilador ao qual estamos acostumados (visando uma ABI fixa que pode vincular código compilado separadamente). A remoção de membros não utilizados só poderia ser feita com a otimização de todo o programa, que proíbe bibliotecas separadas 1 .

Talvez seja necessário concordar com outras unidades de compilação sizeof(foo), mas isso não seria algo que você pudesse derivar de a .hse dependesse da verificação de que nenhuma implementação do comportamento de uma função de membro dependesse de nenhum membro privado.

Lembre-se de que C ++ realmente especifica apenas um programa, não uma maneira de fazer bibliotecas. Especifica o idioma ISO C ++ é compatível com o estilo de implementação que estamos acostumados a (claro), mas implementações que tomar todas as .cppe .harquivos de uma vez e produzir um único executável não extensível auto-suficiente são possíveis.

Se você restringir a implementação o suficiente (sem ABI fixa), a aplicação agressiva de todo o programa da regra as-if torna-se possível.


Nota de rodapé 1: Eu adicionaria " ou exportaria as informações de tamanho de alguma forma para outro código sendo compilado " como uma forma de permitir bibliotecas, se o compilador já pudesse ver as definições de cada função de membro declarada na classe. Mas a resposta de @PasserBy indica que uma biblioteca compilada separadamente poderia ser o que usava os membros privados declarados de maneiras que, em última análise, produzem efeitos colaterais externamente visíveis (como E / S). Portanto, teríamos que descartá-los totalmente.

Sendo assim, membros públicos e privados são equivalentes para os fins de tal otimização.

17 KonradRudolph Dec 08 2020 at 22:26

Se o compilador pode provar que um membro (privado) de uma classe nunca é usado

O compilador não pode provar isso, porque membros privados podem ser usados ​​em outras unidades de compilação. Concretamente, isso é possível no contexto de um ponteiro para um membro em um argumento de modelo de acordo com [temp.spec] / 6 do padrão, conforme descrito originalmente por Johannes Schaub .

Portanto, em resumo: não, o compilador não deve otimizar os membros de dados privados mais do que membros públicos ou protegidos (sujeito à regra as-if).

11 PasserBy Dec 08 2020 at 22:30

Não, porque você pode subverter o sistema de controle de acesso legalmente .

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
}

Dado que o compilador deve consertar a ABI quando Aé usado pela primeira vez, e que nunca pode saber se algum código futuro pode acessar x, ele deve consertar a memória de Apara conter x.