답변:
짧은 대답은 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
&foo
static
foo
foo
주어진 대답뿐만 아니라, 그 컴파일러를 지적 그것의 가치는 초기화 할 필요가 없습니다 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
의미가 없으므로 컴파일러는 한 번 또는 여러 번 추가하는 것을 무시합니다. 오류를 잡으려고하지만 오류가 아닙니다. 대부분의 컴파일러가 작동합니다. constexpr
const
const
const
A로부터const
만에서, 객체const X*
에있는 점X
. 그러나 그것은 요점이 아닙니다. 요점은 자동 객체는 고정 주소를 가질 수 없다는 것입니다. 내가 말했듯이,constexpr
컴파일이 완료되면 의미가 없어 지므로 캐스트 할 것이 없습니다 (객체가 런타임에 존재한다고 보장되지 않기 때문에 아마도 아무것도 없습니다)