차이 무엇 constexpr
과 const
?
- 언제 하나만 사용할 수 있습니까?
- 둘 다 언제 사용할 수 있으며 어떻게 선택해야합니까?
boost/hana
라이브러리 에서이 기사를 constexpr
사용 constexpr
하여 사용할 수없고 사용할 수없는 일부 문제점을 밝힐 수 있습니다 . boost.org/doc/libs/1_69_0/libs/hana/doc/html/…
constexpr
차이 무엇 constexpr
과 const
?
boost/hana
라이브러리 에서이 기사를 constexpr
사용 constexpr
하여 사용할 수없고 사용할 수없는 일부 문제점을 밝힐 수 있습니다 . boost.org/doc/libs/1_69_0/libs/hana/doc/html/…
constexpr
답변:
두 키워드는 함수뿐만 아니라 객체 선언에도 사용할 수 있습니다. 객체에 적용 할 때의 기본적인 차이점 은 다음과 같습니다.
const
객체를 constant 로 선언합니다 . 이는 일단 초기화되면 해당 객체의 값이 변경되지 않으며 컴파일러가이 사실을 최적화에 활용할 수 있음을 보증합니다. 또한 프로그래머가 초기화 후에 수정되지 않은 객체를 수정하는 코드를 작성하지 못하게합니다.
constexpr
Standard가 상수 표현식을 호출하는 데 사용하기에 적합한 객체를 선언합니다 . 그러나 constexpr
이것이 유일한 방법은 아닙니다.
함수에 적용 할 때 기본적인 차이점은 다음과 같습니다.
const
비 정적 멤버 함수에만 사용할 수 있으며 일반적인 함수는 사용할 수 없습니다. 멤버 함수가 비 정적 데이터 멤버를 수정하지 않음을 보증합니다.
constexpr
멤버 함수와 비 멤버 함수 및 생성자 모두와 함께 사용할 수 있습니다. 상수 표현식 에 사용하기에 적합한 함수를 선언합니다 . 컴파일러는 함수가 특정 기준 (7.1.5 / 3,4), 가장 중요하게 (†)를 충족하는 경우에만 수락합니다 .
return
명령문 만 허용됩니다. 생성자의 경우 초기화 목록, typedef 및 정적 어설 션 만 허용됩니다. ( = default
그리고 = delete
생각도 사용할 수 있습니다.)asm
선언, goto
명령문, case
및 이외의 레이블이있는 명령문 default
, try-block, 리터럴이 아닌 유형의 변수 정의, 정적 또는 스레드 스토리지 기간의 변수 정의, 초기화가 수행되지 않은 변수의 정의.위에서 말했듯 constexpr
이 상수 표현식에 사용하기에 적합한 객체뿐만 아니라 객체도 선언합니다. 상수 표현식은 단순한 상수 이상의 것입니다.
템플릿 매개 변수 및 배열 크기 지정자와 같이 컴파일 타임 평가가 필요한 장소에서 사용할 수 있습니다.
template<int N>
class fixed_size_list
{ /*...*/ };
fixed_size_list<X> mylist; // X must be an integer constant expression
int numbers[X]; // X must be an integer constant expression
그러나 참고 :
무언가를 선언 constexpr
한다고해서 컴파일시 평가 될 것이라는 보장은 없습니다. 그것은 사용할 수 있습니다 등을 위해,하지만 런타임에서 평가되는 다른 장소에서 사용뿐만 아니라 수 있습니다.
객체 는 선언 되지 않고 상수 표현식에 사용하기에 적합 할 수 있습니다 constexpr
. 예:
int main()
{
const int N = 3;
int numbers[N] = {1, 2, 3}; // N is constant expression
}
이것은 N
선언 시간에 리터럴로 상수 및 초기화되어 선언되지 않은 경우에도 상수 표현식에 대한 기준을 충족시키기 때문에 가능합니다 constexpr
.
그래서 언제 실제로 사용해야 constexpr
합니까?
객체 같은 N
상기 일정 식으로 사용될 수 없는 선언되고 constexpr
. 다음과 같은 모든 객체에 적용됩니다.
const
[이것은 §5.19 / 2로 인한 것입니다. 상수 표현식에는 "[…] 정수 또는 열거 형의 [...]"glvalue가 아닌 한 lvalue-to-rvalue 수정을 포함하는 하위 표현식이 포함되어서는 안됩니다. 이전에는 이것이 모든 리터럴 유형에 해당한다고 주장했습니다.]
상수 표현식에 사용하기 위해 함수 를 적합하게 하려면 명시 적으로 선언 해야합니다constexpr
. 상수 표현 함수에 대한 기준을 만족시키는 것만으로는 충분하지 않습니다. 예:
template<int N>
class list
{ };
constexpr int sqr1(int arg)
{ return arg * arg; }
int sqr2(int arg)
{ return arg * arg; }
int main()
{
const int X = 2;
list<sqr1(X)> mylist1; // OK: sqr1 is constexpr
list<sqr2(X)> mylist2; // wrong: sqr2 is not constexpr
}
때 나는 / 나는 모두를 사용한다 수 const
와 constexpr
함께?
A. 객체 선언에서. 두 키워드가 선언 할 동일한 객체를 참조 할 때는 필요하지 않습니다. constexpr
의미합니다 const
.
constexpr const int N = 5;
와 같다
constexpr int N = 5;
그러나 키워드가 각각 선언의 다른 부분을 참조하는 상황이있을 수 있습니다.
static constexpr int N = 3;
int main()
{
constexpr const int *NP = &N;
}
여기서는 NP
주소 상수 표현, 즉 그 자체가 상수 표현 인 포인터로 선언됩니다. 여기서 (. 어드레스가 정적 / 전역 상수 식으로 어드레스 오퍼레이터를 적용시킴으로써 생성되는 경우가있다), 양 constexpr
및 const
요구된다 constexpr
항상 식을 의미는 (여기에서 선언되는 NP
동안) const
을 의미한다 int
(그것은 포인터 타입 선언 계속). 를 제거하면 const
표현식이 유효하지 않게됩니다 ((a) 상수가 아닌 객체에 대한 포인터는 상수 표현식이 될 수없고 (b) &N
사실상 포인터에 대한 상수이기 때문에).
B. 멤버 함수 선언에서. C ++ 11에서는을 constexpr
암시 const
하지만 C ++ 14 및 C ++ 17에서는 그렇지 않습니다. C ++ 11에서 다음과 같이 선언 된 멤버 함수
constexpr void f();
로 선언해야합니다
constexpr void f() const;
여전히 C ++ 14에서 const
함수 로 사용할 수 있습니다.
constexpr
은 일반 변수와 같이 상수가 아닌 표현식에서 함수 를 호출하면 완벽하게 합법적이며 함수는 다른 함수처럼 사용된다는 것입니다. 컴파일 타임 (평가할 수 없기 때문에)에서는 평가되지 않습니다. 아마도 당신은 그것이 명백하다고 생각할 것입니다. 그러나 선언 된 함수 constexpr
가 항상 컴파일 타임에 평가 될 것이라고 말하면 잘못된 방식으로 해석 될 수 있습니다.
constexpr
기능이 아닌 객체에 대해 이야기했습니다 . constexpr
객체에 대해 컴파일 타임 값을 강제로 평가 constexpr
하고 함수를 컴파일 타임이나 런타임에 적절하게 평가할 수 있다고 생각 합니다.
mutable
의해 수정 될 수도 있습니다 const
.
const
적용 변수 , 그리고 수정되는 것을 방지 코드에서.
constexpr
이 본 것을 컴파일러에 지시 식 A의 결과를 컴파일 시간 상수 값 이므로 배열 길이가 같은 장소에서 사용될 수를 할당하는 const
등의 변수, 링크 OLI 주어진 것은 우수한 예 많이있다.
기본적으로 이들은 모두 서로 다른 두 가지 개념이며 함께 사용할 수 있습니다.
const
프로그램 이 객체의 값을 변경하지 않도록 보장합니다 . 그러나 const
개체가 어떤 유형의 초기화를 수행하는지 보장하지는 않습니다.
치다:
const int mx = numeric_limits<int>::max(); // OK: runtime initialization
이 함수는 max()
단순히 리터럴 값을 반환합니다. 그러나 이니셜 라이저가 함수 호출이므로 mx
런타임 초기화가 수행됩니다. 따라서 상수 표현식 으로 사용할 수 없습니다 .
int arr[mx]; // error: “constant expression required”
constexpr
매크로와 하드 코딩 된 리터럴을 만들 필요가없는 새로운 C ++ 11 키워드입니다. 또한 특정 조건에서 객체가 정적 초기화를 수행하도록 보장 합니다. 식의 평가 시간을 제어합니다. 시행함으로써 그 표현의 컴파일 타임 평가를 , constexpr
당신이 진정한 정의 할 수 있습니다 상수 표현식 컴파일 시간 상수에 의존하는 코드에서, 말하기, 일반적으로 시간이 중요한 애플리케이션, 시스템 프로그래밍, 템플릿 매우 중요하고 있습니다.
일정한 표현 함수 선언 함수이다 constexpr
. 본문은 비 가상적이어야하며 typedef 및 정적 어설 션을 제외하고 단일 return 문으로 만 구성되어야합니다. 인수와 반환 값은 리터럴 유형이어야합니다. 상수가 아닌 식 인수와 함께 사용할 수 있지만 완료되면 결과가 상수식이 아닙니다.
상수 표현 함수는 성능이나 형식 안전성을 저하시키지 않고 매크로 와 하드 코딩 된 리터럴 을 대체하기 위한 것입니다.
constexpr int max() { return INT_MAX; } // OK
constexpr long long_max() { return 2147483647; } // OK
constexpr bool get_val()
{
bool res = false;
return res;
} // error: body is not just a return statement
constexpr int square(int x)
{ return x * x; } // OK: compile-time evaluation only if x is a constant expression
const int res = square(5); // OK: compile-time evaluation of square(5)
int y = getval();
int n = square(y); // OK: runtime evaluation of square(y)
상수 표현 객체가 선언 된 객체이다 constexpr
. 상수 표현식 또는 상수 표현식 인수가있는 상수 표현식 생성자로 구성된 rvalue로 초기화해야합니다.
상수 표현 객체는 const
사용하기 전에 초기화가 필요하고 초기화 프로그램이 상수 표현식이어야한다는 점을 제외하고 선언 된 것처럼 동작 합니다. 따라서 상수 표현식 객체는 항상 다른 상수 표현식의 일부로 사용될 수 있습니다.
struct S
{
constexpr int two(); // constant-expression function
private:
static constexpr int sz; // constant-expression object
};
constexpr int S::sz = 256;
enum DataPacket
{
Small = S::two(), // error: S::two() called before it was defined
Big = 1024
};
constexpr int S::two() { return sz*2; }
constexpr S s;
int arr[s.two()]; // OK: s.two() called after its definition
상수 표현 생성자가 선언 된 생성자입니다 constexpr
. 멤버 초기화 목록을 가질 수 있지만 typedef 및 정적 어설 션과 별도로 본문이 비어 있어야합니다. 인수에는 리터럴 유형이 있어야합니다.
상수 표현식 생성자는 생성자의 인수가 모두 상수 표현식 인 경우 컴파일러가 컴파일 타임에 객체를 초기화 할 수 있도록합니다.
struct complex
{
// constant-expression constructor
constexpr complex(double r, double i) : re(r), im(i) { } // OK: empty body
// constant-expression functions
constexpr double real() { return re; }
constexpr double imag() { return im; }
private:
double re;
double im;
};
constexpr complex COMP(0.0, 1.0); // creates a literal complex
double x = 1.0;
constexpr complex cx1(x, 0); // error: x is not a constant expression
const complex cx2(x, 1); // OK: runtime initialization
constexpr double xx = COMP.real(); // OK: compile-time initialization
constexpr double imaglval = COMP.imag(); // OK: compile-time initialization
complex cx3(2, 4.6); // OK: runtime initialization
Scott Meyers의 Effective Modern C ++ 책에 대한 팁 constexpr
:
constexpr
객체는 const이며 컴파일 중에 알려진 값으로 초기화됩니다.constexpr
함수는 컴파일 중에 값을 알고있는 인수와 함께 호출 될 때 컴파일 타임 결과를 생성합니다.constexpr
객체와 함수는 객체와 함수가 아닌 것보다 더 넓은 범위의 컨텍스트에서 사용될 수 있습니다 constexpr
.constexpr
객체 또는 함수 인터페이스의 일부입니다.비얀 스트로브 스트 룹에 의해 "언어 4 Editon 프로그래밍은 C ++"의 예약에 따르면
• const를 대략 의미 ''나는이 값을 변경하지 않겠다고 약속 ''(§7.5). 주로 인터페이스를 지정하는 데 사용되므로 데이터를 수정하지 않아도 데이터를 함수에 전달할 수 있습니다.
컴파일러는 const의 약속을 시행합니다.
• constexpr : 대략 ''컴파일 타임에 평가됨 ''을 의미합니다 (§10.4). 이것은 주로 상수를 지정하는 데 사용됩니다
. 예를 들면 다음과 같습니다.
const int dmv = 17; // dmv is a named constant
int var = 17; // var is not a constant
constexpr double max1 = 1.4*square(dmv); // OK if square(17) is a constant expression
constexpr double max2 = 1.4∗square(var); // error : var is not a constant expression
const double max3 = 1.4∗square(var); //OK, may be evaluated at run time
double sum(const vector<double>&); // sum will not modify its argument (§2.2.5)
vector<double> v {1.2, 3.4, 4.5}; // v is not a constant
const double s1 = sum(v); // OK: evaluated at run time
constexpr double s2 = sum(v); // error : sum(v) not constant expression
상수 표현식, 즉 컴파일러가 평가할 표현식에서 함수를 사용하려면 constexpr 로 정의해야합니다 .
예를 들면 다음과 같습니다.
constexpr double square(double x) { return x∗x; }
constexpr이 되려면 함수는 단순해야합니다. 값을 계산하는 return-statement입니다. constexpr 함수는 상수가 아닌 인수에 사용할 수 있지만 완료되면 상수 표현식이 아닙니다. 상수 표현식이 필요없는 컨텍스트에서 상수 표현식이 아닌 인수로 constexpr 함수를 호출 할 수 있으므로 상수 표현식과 변수에 대해 동일한 함수를 두 번 정의하지 않아도됩니다.
일부 장소에서는 언어 규칙 (예 : 배열 범위 (§2.2.5, §7.3), 대소 문자 레이블 (§2.2.4, §9.4.2), 일부 템플릿 인수 (§25.2)에 따라 상수 표현식이 필요합니다. constexpr을 사용하여 선언 된 상수). 다른 경우에는 컴파일 타임 평가가 성능에 중요합니다. 성능 문제와 상관없이 (불변 상태의 객체에 대한) 불변성의 개념은 중요한 설계 문제입니다 (§10.4).
모두 const
와 constexpr
변수와 함수에 적용 할 수 있습니다. 그것들은 서로 비슷하지만 실제로는 매우 다른 개념입니다.
모두 const
와 constexpr
평균 그 값은 초기화 후 변경할 수 없습니다. 예를 들어 :
const int x1=10;
constexpr int x2=10;
x1=20; // ERROR. Variable 'x1' can't be changed.
x2=20; // ERROR. Variable 'x2' can't be changed.
간의 주된 차이 const
및 constexpr
그들의 초기 값이 공지 된 시간 (평가). const
변수 값은 컴파일 타임과 런타임 모두에서 평가할 수 있지만 constexpr
항상 컴파일 타임에 평가됩니다. 예를 들면 다음과 같습니다.
int temp=rand(); // temp is generated by the the random generator at runtime.
const int x1=10; // OK - known at compile time.
const int x2=temp; // OK - known only at runtime.
constexpr int x3=10; // OK - known at compile time.
constexpr int x4=temp; // ERROR. Compiler can't figure out the value of 'temp' variable at compile time so `constexpr` can't be applied here.
컴파일 타임 또는 런타임에 값을 알고 있는지 확인하는 주요 이점은 컴파일 타임 상수가 필요할 때마다 컴파일 타임 상수를 사용할 수 있다는 것입니다. 예를 들어 C ++에서는 가변 길이로 C- 배열을 지정할 수 없습니다.
int temp=rand(); // temp is generated by the the random generator at runtime.
int array1[10]; // OK.
int array2[temp]; // ERROR.
따라서 다음을 의미합니다.
const int size1=10; // OK - value known at compile time.
const int size2=temp; // OK - value known only at runtime.
constexpr int size3=10; // OK - value known at compile time.
int array3[size1]; // OK - size is known at compile time.
int array4[size2]; // ERROR - size is known only at runtime time.
int array5[size3]; // OK - size is known at compile time.
그래서 const
변수를 정의 할 수 있습니다 모두 컴파일 시간 상수 와 같은 size1
그 배열의 크기와 지정하는 데 사용할 수 있습니다 런타임 상수 처럼 size2
만 런타임에 알려진 및 배열의 크기를 정의하는 데 사용할 수 없습니다. 반면에 constexpr
항상 배열 크기를 지정할 수있는 컴파일 시간 상수를 정의하십시오.
모두 const
와 constexpr
너무 기능에 적용 할 수 있습니다. const
함수 멤버 함수 (있어서, 오퍼레이터)의 적용에 있어야 const
있어서 그들의 부재 (비 고정) 필드의 값을 변경할 수없는 키워드 수단. 예를 들어.
class test
{
int x;
void function1()
{
x=100; // OK.
}
void function2() const
{
x=100; // ERROR. The const methods can't change the values of object fields.
}
};
A constexpr
는 다른 개념입니다. 컴파일 시간 상수가 인수로 전달되면 컴파일 시간에 평가할 수있는 함수로 함수 (멤버 또는 비 멤버)를 표시합니다 . 예를 들어 이것을 작성할 수 있습니다.
constexpr int func_constexpr(int X, int Y)
{
return(X*Y);
}
int func(int X, int Y)
{
return(X*Y);
}
int array1[func_constexpr(10,20)]; // OK - func_constexpr() can be evaluated at compile time.
int array2[func(10,20)]; // ERROR - func() is not a constexpr function.
int array3[func_constexpr(10,rand())]; // ERROR - even though func_constexpr() is the 'constexpr' function, the expression 'constexpr(10,rand())' can't be evaluated at compile time.
그런데 constexpr
함수는 상수가 아닌 인수가 전달 되더라도 호출 할 수있는 일반 C ++ 함수입니다. 그러나이 경우 비 constprpr 값을 얻습니다.
int value1=func_constexpr(10,rand()); // OK. value1 is non-constexpr value that is evaluated in runtime.
constexpr int value2=func_constexpr(10,rand()); // ERROR. value2 is constexpr and the expression func_constexpr(10,rand()) can't be evaluated at compile time.
는 constexpr
또한 멤버 함수 (메소드) 연산자 생성자에도 적용될 수있다. 예를 들어.
class test2
{
static constexpr int function(int value)
{
return(value+1);
}
void f()
{
int x[function(10)];
}
};
더 '미친'샘플.
class test3
{
public:
int value;
// constexpr const method - can't chanage the values of object fields and can be evaluated at compile time.
constexpr int getvalue() const
{
return(value);
}
constexpr test3(int Value)
: value(Value)
{
}
};
constexpr test3 x(100); // OK. Constructor is constexpr.
int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time.
constexpr int
존재하지만 철자const int
A const int var
는 런타임시 동적으로 값으로 설정 될 수 있으며 해당 값으로 설정되면 더 이상 변경할 수 없습니다.
A constexpr int var
는 런타임에 동적으로 설정할 수 없지만 컴파일 타임에 동적으로 설정할 수 있습니다. 일단 해당 값으로 설정되면 더 이상 변경할 수 없습니다.
다음은 확실한 예입니다.
int main(int argc, char*argv[]) {
const int p = argc;
// p = 69; // cannot change p because it is a const
// constexpr int q = argc; // cannot be, bcoz argc cannot be computed at compile time
constexpr int r = 2^3; // this works!
// r = 42; // same as const too, it cannot be changed
}
위의 스 니펫은 잘 컴파일되며 오류가 발생하는 코드를 주석 처리했습니다.
여기서 주목할 핵심 개념은 compile time
및 의 개념입니다 run time
. ** know **
컴파일 타임에 가능한 한 많은 것을 런타임에 성능을 향상시키기 위해 C ++에 새로운 혁신이 도입되었습니다 .
나는 어떤 대답이 실제로 부작용이 무엇인지, 실제로 무엇이 무엇인지 명확하게 밝히지 않는다고 생각합니다.
constexpr
그리고 const
네임 스페이스 / 파일 범위에서 리터럴 또는 표현식으로 초기화 될 때 동일합니다. 그러나 함수를 사용하면 const
모든 함수로 초기화 할 수 있지만 constexpr
비 constprpr (constexpr 또는 constempr이 아닌 표현식으로 표시되지 않은 함수)으로 초기화하면 컴파일러 오류가 발생합니다. 모두 constexpr
와 const
암시 적으로 내부 연결은 (물론 실제로, 그들은 -O1 강한 컴파일하면 링크 단계에 도착 생존하지 않으며, 변수에 있습니다 static
에 대한 내부 (로컬) 링커 심볼을 방출하는 컴파일러를 강요하지 않습니다 const
또는 constexpr
경우에 -O1 또는 강한, 그것은이 작업을 수행하는 유일한 시간은 변수의 주소를 가지고가는 경우입니다. const
와 constexpr
표현하지 않는 내부 기호 것 extern
즉,extern constexpr/const int i = 3;
사용해야합니다). 함수에서 constexpr
함수가 영구적으로 (관계없이 연결 단계에 도달하지하게 extern
하거나 inline
, 정의 또는 -O0 또는 -Ofast에서) 반면 const
하지 않을하고, static
그리고 inline
단지 -O1 이상에서이 효과가 있습니다. 때 const
/의 constexpr
변수가에 의해 초기화되는 constexpr
기능, 부하는 항상 최적화 플래그 함께 최적화되어 있지만, 기능은 경우 그것은 밖으로 최적화되지 않습니다 static
또는 inline
변수가없는 경우, 또는 const
/ constexpr
.
표준 컴파일 (-O0)
#include<iostream>
constexpr int multiply (int x, int y)
{
return x * y;
}
extern const int val = multiply(10,10);
int main () {
std::cout << val;
}
컴파일
val:
.long 100 //extra external definition supplied due to extern
main:
push rbp
mov rbp, rsp
mov esi, 100 //substituted in as an immediate
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
하나
#include<iostream>
const int multiply (int x, int y)
{
return x * y;
}
const int val = multiply(10,10); //constexpr is an error
int main () {
std::cout << val;
}
컴파일
multiply(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-8]
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov eax, DWORD PTR val[rip]
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
mov esi, 10
mov edi, 10
call multiply(int, int)
mov DWORD PTR val[rip], eax
이것은 파일 범위 변수 constexpr
의 초기화가 const/constexpr
컴파일 타임에 발생하고 전역 기호를 생성하지 않는 반면,이를 사용하지 않으면 main
런타임 전에 초기화가 발생 한다는 것을 분명히 보여줍니다 .
-Ofast를 사용하여 컴파일
-Ofast조차도 부하를 최적화하지 않습니다! https://godbolt.org/z/r-mhif , 그래서 당신은 필요 constexpr
constexpr
constexpr
동일한 결과를 위해 다른 함수 내에서 함수를 호출 할 수도 있습니다 . constexpr
함수에서 함수에서 컴파일 타임에 수행 할 수없는 것을 사용하지 못하게합니다. 예를 들어,에 대한 <<
운영자 호출 std::cout
.
constexpr
블록 범위에서 non-constexpr 함수로 초기화되면 오류가 발생한다는 점에서 동일하게 작동합니다. 값도 즉시 대체됩니다.
결국 주요 목적은 C의 인라인 함수와 비슷하지만 함수가 파일 범위 변수를 초기화하는 데 사용되는 경우에만 효과적입니다 (함수는 C에서 수행 할 수 없지만 파일의 동적 초기화를 허용하기 때문에 C ++에서 가능합니다. 범위 변수)를 제외하고는 함수가 전역 / 로컬 심볼을 링커로 내보낼 수 없으며 C 에서도 사용할 extern/static
수 있습니다 inline
. constexpr
C 및 C ++에서 -O1 최적화를 사용하여 블록 범위 변수 할당 함수를 인라인 할 수 있습니다 .
우선, 둘 다 C ++의 한정자입니다. const로 선언 된 변수는 초기화해야하며 나중에 변경할 수 없습니다. 따라서 일반적으로 const로 선언 된 변수는 컴파일하기 전에도 값을 갖습니다.
그러나 constexpr의 경우 약간 다릅니다.
constexpr의 경우 프로그램 컴파일 중에 평가할 수있는 표현식을 제공 할 수 있습니다.
분명히 constexper로 선언 된 변수는 나중에 const처럼 변경할 수 없습니다.
constexpr
컴파일 타임 상수를 만듭니다.const
단순히 값을 변경할 수 없음을 의미합니다.