2012-12-13 3 views
98

함수 안에 변수가있는 경우 (예 : 큰 배열) staticconstexpr을 모두 선언하는 것이 합리적입니까? constexpr은 컴파일 타임에 배열이 생성되도록 보장하므로 static은 쓸모 없습니까?정적 constexpr 변수가 의미가 있습니까?

void f() { 
    static constexpr int x [] = { 
     // a few thousand elements 
    }; 
    // do something with the array 
} 

실제로 생성 된 코드 또는 의미의 용어가 무엇을하고있는 static인가?

+11

'constexpr'는 컴파일 타임을 보장하지 않습니다. 컴파일러는 런타임에'constexpr' 물건을 자유롭게 평가할 수 있습니다. 컴파일 타임에 알 필요가있는 맥락에서 뭔가를 사용하면 컴파일 타임에 뭔가를 평가해야만합니다. – Praetorian

+0

나는 @Praetorian이 정확하다고 믿고'static'은 컴파일 타임에뿐만 아니라 컴파일 타임 상수로만 저장된다는 것을 보장합니다. 나는'static '없이는 함수의 각 호출시 (거대한) 배열을 스택에 밀어 넣는 것이 이론적으로는 가능하다고 생각한다. –

+3

@AndrewLazarus는 이론적으로 모든 호출에서 스택에 배열을 밀어 넣기 위해 이론적으로는 준수 할뿐만 아니라 이론적으로 필요합니다 (as-if 규칙을 모듈화해야 함). 실제로, 나의 경험에서, 그것은 꽤 잘 항상 발생합니다. 자세한 내용은 내 대답을 참조하십시오. – rici

답변

120

짧은 대답은 static이 유용 할뿐만 아니라 언제나 바람직 할 것입니다.

먼저 staticconstexpr은 서로 완전히 독립적입니다. static은 실행 중 객체의 수명을 정의합니다. constexpr은 컴파일하는 동안 개체를 사용할 수 있도록 지정합니다. 컴파일과 실행은 시간과 공간에서 분리되고 불연속 적입니다. 따라서 일단 프로그램이 컴파일되면 constexpr은 더 이상 적합하지 않습니다.

는 모든 변수는 constexpr 암시 const하지만 const하고 static 거의 직교 선언 (static const 정수와의 상호 작용을 제외하고.)

C++ 개체 모델 (§ 1.9) 비트 필드를 제외한 모든 개체를 차지해야 적어도 1 바이트의 메모리와 주소를 가짐. 또한 주어진 순간에 프로그램에서 관찰 할 수있는 그러한 모든 객체는 서로 다른 주소를 가져야한다 (6 절). 이것은 컴파일러가 as-if 원칙을 피할 수 있기 때문에 컴파일러가 로컬 정적이 아닌 const 배열을 사용하여 함수를 호출 할 때마다 스택에 새 배열을 만들 필요가 없습니다. 관찰 되야한다.

불행히도 함수가 자명하지 않은 경우 (예를 들어 번역 단위 내에서 본문이 보이지 않는 다른 함수를 호출하지 않는 한) 쉽지 않을 것입니다. 주소입니다. 따라서 대부분의 경우 비 정적 인 const(expr) 배열은 호출 할 때마다 스택에 다시 만들어 져야합니다. 컴파일 타임에 컴파일 할 수 없게됩니다.

한편 로컬 static const 개체는 모든 옵저버가 공유하며 정의 된 기능이 호출되지 않아도 초기화 될 수 있습니다. 따라서 위의 어느 것도 적용되지 않으며 컴파일러는 인스턴스를 하나만 생성 할뿐만 아니라 무료입니다. 읽기 전용 저장소에서 단일 인스턴스를 생성 할 수 있습니다.

예를 들어 static constexpr을 사용해야합니다.

그러나 static constexper을 사용하지 않으려는 경우가 있습니다. constexpr 선언 된 개체가 ODR- 사용되거나 static으로 선언되지 않는 한 컴파일러는이 개체를 전혀 포함하지 않아도됩니다. 불필요한 바이트로 컴파일 된 프로그램을 오염시키지 않으면 서 컴파일 시간 임시 constexpr 배열을 사용할 수 있으므로 매우 유용합니다. 이 경우 static을 사용하려고하지 않을 것입니다. static은 런타임에 객체를 강제 실행하기 때문입니다.

+1

내가이 말을 할 때 나는 이것을 생각하고 있었다. ISTM'constexpr'은'const'과 달리 항상 읽기 전용 저장소에 둘 수 있습니다 ('constexpr' [?]를 버리면 안됩니다). 그러면 스택에 새로운 사본을 넣을 필요가 없습니다. 'const' 변수가 필요할 것입니다. 일정한 리터럴 문자열 풀링과 비슷합니다. 그러나 그것이 합법적인지 나는 모른다. –

+1

@AndrewLazarus, 당신은'const' 객체로부터'const'를 버릴 수없고'X'를 가리키는'const X *'에서만 캐스팅 할 수 있습니다. 그러나 그것은 중요한 것이 아닙니다. 요점은 자동 개체가 정적 주소를 가질 수 없다는 것입니다. 앞에서 말했듯이 컴파일이 끝나면'constexpr'은 의미가 없으므로 버려 질 것이 없습니다. 런타임시 객체가 존재하지 않을 수도 있기 때문에 아무 것도 할 수 없습니다. – rici

+0

In C++ 1y, contexpr 함수는 const가 아닙니다. – refi64

관련 문제