답변:
짧은 대답은 static유용 할뿐만 아니라 항상 원할 것입니다.
첫째, 그 노트 static와는 constexpr서로 완전히 독립적입니다. static실행 중 객체의 수명을 정의합니다. constexpr컴파일 중에 오브젝트를 사용할 수 있도록 지정합니다. 컴파일과 실행은 시간과 공간 모두에서 분리되고 불 연속적입니다. 따라서 프로그램이 컴파일되면 constexpr더 이상 관련이 없습니다.
선언 된 모든 변수는 constexpr암시입니다 const만 const과 static거의 직교 (과의 상호 작용을 제외하고 static const정수.)
C++객체 모델 (§1.9)의 모든 비트 필드는 메모리의 적어도 하나의 바이트를 차지하고 주소가 아닌 다른 오브젝트해야; 또한 주어진 순간에 프로그램에서 관찰 할 수있는 그러한 모든 객체는 별개의 주소를 가져야한다 (문단 6). 컴파일러는 로컬 비 정적 const 배열로 함수를 호출 할 때마다 스택에 새 배열을 만들 필요가 없습니다. 컴파일러는 as-if원칙적으로 피난처를 취할 수 있기 때문에 다른 객체가 없다는 것을 증명할 수 있기 때문입니다 관찰했다.
정의가 다소간에 배열이 주소이기 때문에 함수가 사소하지 않으면 (예를 들어, 번역 단위 내에서 본문이 보이지 않는 다른 함수를 호출하지 않는 한) 안타깝게도 쉽게 증명할 수 없습니다. 따라서 대부분의 경우 정적이 아닌 const(expr)배열은 호출 할 때마다 스택에서 다시 작성해야하므로 컴파일시 배열을 계산할 수있는 지점을 잃게됩니다.
반면, 로컬 static const객체는 모든 옵저버가 공유하며, 정의 된 함수가 호출되지 않더라도 초기화 될 수 있습니다. 따라서 위의 어느 것도 적용되지 않으며 컴파일러는 단일 인스턴스 만 생성 할뿐 아니라 자유롭게 사용할 수 있습니다. 읽기 전용 스토리지에서 인스턴스 하나를 자유롭게 생성 할 수 있습니다.
따라서 static constexpr귀하의 예에서 분명히 사용해야 합니다.
그러나을 사용하고 싶지 않은 경우가 있습니다 static constexpr. 않는 constexpr선언 된 개체 중 하나입니다 ODR-사용 또는 선언이 static컴파일러는 전혀 포함시키지 무료입니다. constexpr불필요한 바이트로 컴파일 된 프로그램을 오염시키지 않고 컴파일 타임 임시 배열을 사용할 수 있기 때문에 매우 유용 합니다. 이 경우 런타임에 객체가 존재하게 될 가능성이 static있으므로 를 사용하고 싶지 않습니다 static.
static하고 constexpr있지만 서로 다른 일을하고, 직교 및 독립적이라고 설명한다. 그런 다음 ODR 사용을 무시하므로 유용하지 않은 두 가지를 결합하지 않는 이유를 언급합니다. 정적이 런타임 용이므로 constexpr과 함께 정적을 사용해야하는 이유는 여전히 알지 못합니다. constexpr을 사용하여 static이 중요한 이유를 설명하지 않았습니다.
static constexpr( 중요한 배열이 모든 함수 호출에서 다시 작성되는 것을 막는다) 의 중요성을 설명했다고 생각 했지만 더 명확하게 할 수있는 단어를 수정했습니다. 감사.
constexpr상수 변수가 컴파일 타임 컨텍스트에서만 사용되고 런타임에는 필요 static하지 않으면 런타임에 도달 할 때까지 값이 효과적으로 "인라인"되었으므로 의미가 없습니다. 그러나 constexpr런타임 컨텍스트에서 사용되는 경우 (즉, 암시 적 constexpr으로 변환해야 const하며 런타임 코드의 실제 주소로 사용 가능 static해야 함) ODR 준수 등을 보장해야합니다. 적어도 내 이해입니다.
static constexpr int foo = 100;. 코드가 다음과 같은 작업을 수행하지 않는 한 컴파일러가 foo리터럴 대신 모든 곳의 사용을 대체 할 수없는 이유는 없습니다 . 따라서 런타임에는 존재하지 않기 때문에 on 은이 경우 유용 하지 않습니다. 다시 컴파일러까지 모두. 100&foostaticfoofoo
주어진 대답뿐만 아니라, 그 컴파일러를 지적 그것의 가치는 초기화 할 필요가 없습니다 constexpr차이 것을 알고, 컴파일시에 변수 constexpr및 static constexpr그 사용하는 것입니다 static constexpr당신이 변수가 한 번만 초기화되어 있는지 확인합니다.
다음 코드는 constexpr변수가 여러 번 (동일한 값으로) static constexpr초기화 되는 반면 한 번만 초기화 되는 방법을 보여줍니다 .
또한 코드는 constexpr와의 const조합 에 대한 장점을 비교합니다 static.
#include <iostream>
#include <string>
#include <cassert>
#include <sstream>
const short const_short = 0;
constexpr short constexpr_short = 0;
// print only last 3 address value numbers
const short addr_offset = 3;
// This function will print name, value and address for given parameter
void print_properties(std::string ref_name, const short* param, short offset)
{
// determine initial size of strings
std::string title = "value \\ address of ";
const size_t ref_size = ref_name.size();
const size_t title_size = title.size();
assert(title_size > ref_size);
// create title (resize)
title.append(ref_name);
title.append(" is ");
title.append(title_size - ref_size, ' ');
// extract last 'offset' values from address
std::stringstream addr;
addr << param;
const std::string addr_str = addr.str();
const size_t addr_size = addr_str.size();
assert(addr_size - offset > 0);
// print title / ref value / address at offset
std::cout << title << *param << " " << addr_str.substr(addr_size - offset) << std::endl;
}
// here we test initialization of const variable (runtime)
void const_value(const short counter)
{
static short temp = const_short;
const short const_var = ++temp;
print_properties("const", &const_var, addr_offset);
if (counter)
const_value(counter - 1);
}
// here we test initialization of static variable (runtime)
void static_value(const short counter)
{
static short temp = const_short;
static short static_var = ++temp;
print_properties("static", &static_var, addr_offset);
if (counter)
static_value(counter - 1);
}
// here we test initialization of static const variable (runtime)
void static_const_value(const short counter)
{
static short temp = const_short;
static const short static_var = ++temp;
print_properties("static const", &static_var, addr_offset);
if (counter)
static_const_value(counter - 1);
}
// here we test initialization of constexpr variable (compile time)
void constexpr_value(const short counter)
{
constexpr short constexpr_var = constexpr_short;
print_properties("constexpr", &constexpr_var, addr_offset);
if (counter)
constexpr_value(counter - 1);
}
// here we test initialization of static constexpr variable (compile time)
void static_constexpr_value(const short counter)
{
static constexpr short static_constexpr_var = constexpr_short;
print_properties("static constexpr", &static_constexpr_var, addr_offset);
if (counter)
static_constexpr_value(counter - 1);
}
// final test call this method from main()
void test_static_const()
{
constexpr short counter = 2;
const_value(counter);
std::cout << std::endl;
static_value(counter);
std::cout << std::endl;
static_const_value(counter);
std::cout << std::endl;
constexpr_value(counter);
std::cout << std::endl;
static_constexpr_value(counter);
std::cout << std::endl;
}
가능한 프로그램 출력 :
value \ address of const is 1 564
value \ address of const is 2 3D4
value \ address of const is 3 244
value \ address of static is 1 C58
value \ address of static is 1 C58
value \ address of static is 1 C58
value \ address of static const is 1 C64
value \ address of static const is 1 C64
value \ address of static const is 1 C64
value \ address of constexpr is 0 564
value \ address of constexpr is 0 3D4
value \ address of constexpr is 0 244
value \ address of static constexpr is 0 EA0
value \ address of static constexpr is 0 EA0
value \ address of static constexpr is 0 EA0
보시다시피 키워드는 초기화가 한 번만 수행되도록하는 constexpr동안 여러 번 static초기화됩니다 (주소는 동일하지 않음) .
constexpr const short constexpr_short되면 에러를 줄 수 없습니다
constexpr const의미가 없으므로 컴파일러는 한 번 또는 여러 번 추가하는 것을 무시합니다. 오류를 잡으려고하지만 오류가 아닙니다. 대부분의 컴파일러가 작동합니다. constexprconstconst
constA로부터const만에서, 객체const X*에있는 점X. 그러나 그것은 요점이 아닙니다. 요점은 자동 객체는 고정 주소를 가질 수 없다는 것입니다. 내가 말했듯이,constexpr컴파일이 완료되면 의미가 없어 지므로 캐스트 할 것이 없습니다 (객체가 런타임에 존재한다고 보장되지 않기 때문에 아마도 아무것도 없습니다)