컴파일러가 개인 데이터 멤버를 최적화 할 수 있습니까?

Dec 08 2020

컴파일러가 잠재적 인 친구를 포함하여 클래스의 (개인) 멤버가 절대 사용되지 않음을 증명할 수 있다면 표준은 컴파일러가 클래스의 메모리 공간에서이 멤버를 제거하도록 허용합니까?

컴파일 타임에 보호되거나 공개 된 구성원에게는 불가능하다는 것은 자명하지만, 그러한 증명을 구성하기 위해 개인 데이터 구성원과 관련하여 가능한 상황이있을 수 있습니다.


관련 질문 :

  • 공개, 개인 및 보호의 무대 뒤에서 (이 질문을 불러 일으켰습니다)
  • C ++ 컴파일러가 참조되지 않은 로컬 개체 (자동 개체에 대해) 를 최적화 할 수 있습니까?
  • 정적 변수는 항상 메모리를 사용합니까? (정적 개체에 대해)

답변

31 PeterCordes Dec 08 2020 at 23:19

이론적으로는 가능하지만 (사용하지 않는 공용 멤버와 함께) 우리가 익숙한 종류의 컴파일러 생태계에서는 가능하지 않습니다 (별도로 컴파일 된 코드를 연결할 수있는 고정 ABI를 목표로 함). 사용하지 않는 멤버를 제거하는 것은 별도의 라이브러리를 금지하는 전체 프로그램 최적화를 통해서만 수행 할 수 있습니다 1 .

다른 컴파일 단위는에 동의해야 할 수도 sizeof(foo)있지만 .h멤버 함수의 동작 구현이 private 멤버에 의존하지 않는지 확인하는 데 의존 하는 경우 에서 파생 할 수있는 것이 아닙니다 .

C ++는 실제로 라이브러리를 수행하는 방법이 아니라 하나의 프로그램 만 지정합니다. ISO C ++가 지정하는 언어는 (물론) 우리가 익숙한 구현 스타일과 호환되지만 모든 .cpp.h파일을 한 번에 가져와 단일 자체 포함 비 확장 실행 파일을 생성하는 구현 이 가능합니다.

구현을 충분히 제한하면 (고정 ABI 없음) as-if 규칙의 적극적인 전체 프로그램 적용이 가능해집니다.


각주 1 : 컴파일러가 클래스에서 선언 된 모든 멤버 함수에 대한 정의를 이미 볼 수있는 경우 라이브러리를 허용하는 방법으로 " 또는 컴파일중인 다른 코드에 크기 정보를 내보내려고 "했습니다. 그러나 @PasserBy의 답변은 개별적으로 컴파일 된 라이브러리가 궁극적으로 외부에서 볼 수있는 부작용 (예 : I / O)을 생성하는 방식으로 선언 된 private 멤버를 사용하는 것일 수 있다고 지적합니다. 그래서 우리는 그것들을 완전히 배제해야합니다.

이를 감안할 때 공개 및 비공개 구성원은 이러한 최적화 목적에 동일합니다.

17 KonradRudolph Dec 08 2020 at 22:26

컴파일러가 클래스의 (개인) 멤버가 사용되지 않음을 증명할 수있는 경우

다른 컴파일 단위에서 private 멤버를 사용할 수 있기 때문에 컴파일러 는이를 증명할 수 없습니다 . 구체적으로 이것은 Johannes Schaub에 의해 원래 설명 된대로 표준의 [temp.spec] / 6 에 따라 템플릿 인수의 멤버에 대한 포인터 컨텍스트에서 가능합니다 .

요약하자면, 컴파일러는 공용 또는 보호 된 멤버 (as-if 규칙에 따라)보다 더 이상 개인 데이터 멤버를 최적화하지 않아야합니다.

11 PasserBy Dec 08 2020 at 22:30

아니요, 합법적으로 출입 통제 시스템을 전복시킬 수 있기 때문 입니다.

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
}

컴파일러 A가를 처음 사용할 때 ABI를 수정해야 하고 향후 코드가에 액세스 할 수 있는지 여부를 알 수 없다는 점을 감안할 때 를 포함 x하려면의 메모리를 수정해야 A합니다 x.