C ++에서 전역 상수 정의
여러 소스 파일에서 볼 수 있도록 C ++에서 상수를 정의하고 싶습니다. 다음과 같은 방법으로 헤더 파일에 정의 할 수 있습니다.
#define GLOBAL_CONST_VAR 0xFF
int GLOBAL_CONST_VAR = 0xFF;
- 값을 returing 일부 기능 (예를 들어
int get_GLOBAL_CONST_VAR()
) enum { GLOBAL_CONST_VAR = 0xFF; }
const int GLOBAL_CONST_VAR = 0xFF;
extern const int GLOBAL_CONST_VAR;
그리고 하나의 소스 파일에서const int GLOBAL_CONST_VAR = 0xFF;
옵션 (1)-확실히 사용하고 싶은 옵션이 아닙니다.
옵션 (2)-헤더 파일을 사용하여 각 개체 파일의 변수 인스턴스 정의
옵션 (3)-IMO는 대부분의 경우 과잉 살인입니다.
옵션 (4)-enum에 구체적인 유형이 없기 때문에 많은 경우 좋지 않을 수 있습니다 (C ++ 0X는 유형을 정의 할 가능성을 추가합니다).
따라서 대부분의 경우 (5)와 (6) 중에서 선택해야합니다. 내 질문 :
- (5) 또는 (6) 무엇을 선호합니까?
- 왜 (5)는 괜찮고 (2)는 괜찮습니까?
(5) 당신이 말하고 싶은 것을 정확하게 말합니다. 또한 컴파일러가 대부분의 시간을 최적화 할 수 있습니다. (6) 반면에 컴파일러는 당신이 결국 그것을 변경할지 여부를 알지 못하기 때문에 컴파일러가 그것을 최적화하지 못하게 할 것입니다.
확실히 옵션 5로 가십시오-유형이 안전하고 컴파일러가 최적화 할 수 있도록합니다 (해당 변수의 주소를 사용하지 마십시오 :) 또한 헤더에있는 경우 전역 범위를 오염시키지 않도록 네임 스페이스에 붙여 넣으십시오.
// header.hpp
namespace constants
{
const int GLOBAL_CONST_VAR = 0xFF;
// ... other related constants
} // namespace constants
// source.cpp - use it
#include <header.hpp>
int value = constants::GLOBAL_CONST_VAR;
(5)는 GLOBAL_CONST_VAR
모든 번역 단위에서 ICE (Integral Constant Expression)로 정의되기 때문에 (6)보다 "낫습니다" . 예를 들어, 모든 번역 단위에서 배열 크기 및 케이스 레이블로 사용할 수 있습니다. (6)의 경우 GLOBAL_CONST_VAR
정의 된 번역 단위에서 정의 지점 이후에만 ICE가됩니다. 다른 번역 단위에서는 ICE로 작동하지 않습니다.
그러나 (5)는 GLOBAL_CONST_VAR
내부 연결을 제공합니다 . 즉,의 "주소 ID"가 GLOBAL_CONST_VAR
각 번역 단위에서 &GLOBAL_CONST_VAR
다를 것입니다. 즉, 각 번역 단위에서 다른 포인터 값을 제공합니다. 대부분의 사용 사례에서 이것은 중요하지 않지만 일관된 전역 "주소 ID"를 가진 상수 개체가 필요한 경우 (6)으로 이동하여 상수의 ICE-ness를 희생해야합니다. 방법.
또한 상수의 ICE-ness가 문제가되지 않고 (정수 유형이 아님) 유형의 크기가 커지면 (스칼라 유형이 아님) 일반적으로 (6)이 (5)보다 더 나은 접근 방식이됩니다.
(2)는 GLOBAL_CONST_VAR
기본적으로 (2)에 외부 연결이 있기 때문에 OK가 아닙니다 . 헤더 파일에 넣으면 일반적으로에 대한 여러 정의가 발생 GLOBAL_CONST_VAR
하며 이는 오류입니다. const
C ++의 객체는 기본적으로 내부 연결이 있습니다. 이것이 (5)가 작동하는 이유입니다 (그리고 위에서 말했듯 GLOBAL_CONST_VAR
이 각 번역 단위에서 별도의 독립적 인 이유를 얻습니다 ).
C ++ 17부터 선언 할 수있는 옵션이 있습니다.
inline extern const int GLOBAL_CONST_VAR = 0xFF;
헤더 파일에서. 이렇게하면 모든 번역 단위 (방법 (5)와 마찬가지로)에서 ICE를 제공하는 동시에 전역 주소 ID를 유지합니다 GLOBAL_CONST_VAR
. 모든 번역 단위에서 동일한 주소를 갖게됩니다.
상수가 되려면 상수로 표시해야합니다. 이것이 제 생각에 2가 나쁜 이유입니다.
컴파일러는 값의 const 특성을 사용하여 일부 수학 및 실제로 값을 사용하는 다른 연산을 확장 할 수 있습니다.
5에서 6 사이의 선택-흠; 5 기분이 나아졌습니다.
6)에서 값은 선언에서 불필요하게 분리됩니다.
나는 일반적으로 상수 등 만 정의하는 이러한 헤더 중 하나 이상을 가지고 있으며 다른 '영리한'것은 없습니다. 어디서나 쉽게 포함될 수있는 멋진 경량 헤더.
C ++ 11 이상을 사용하는 경우 컴파일 시간 상수를 사용해보십시오.
constexpr int GLOBAL_CONST_VAR{ 0xff };
두 번째 질문에 답하려면 :
(2) 단일 정의 규칙을 위반하여 불법입니다. GLOBAL_CONST_VAR
포함 된 모든 파일, 즉 두 번 이상 정의합니다 . (5)는 하나의 정의 규칙이 적용되지 않기 때문에 합법적입니다. 각각 GLOBAL_CONST_VAR
은 포함 된 해당 파일에 로컬 인 별도의 정의입니다. 이러한 모든 정의는 물론 동일한 이름과 값을 공유하지만 주소는 다를 수 있습니다.
const int GLOBAL_CONST_VAR = 0xFF;
상수이기 때문에!
귀하의 요구 사항에 따라 다릅니다. (5)는 대부분의 일반적인 사용에 가장 적합하지만 종종 모든 개체 파일에서 저장 공간을 계속 차지하게됩니다. (6) 중요한 상황에서이 문제를 해결할 수 있습니다.
(4) 또한 우선 순위가 저장 공간이 할당되지 않도록 보장하는 경우 적절한 선택이지만 물론 정수 상수에 대해서만 작동합니다.
#define GLOBAL_CONST_VAR 0xFF // this is C code not C++
int GLOBAL_CONST_VAR = 0xFF; // it is not constant and maybe not compilled
Some function returing the value (e.g. int get_LOBAL_CONST_VAR()) // maybe but exists better desision
enum { LOBAL_CONST_VAR = 0xFF; } // not needed, endeed, for only one constant (enum elms is a simple int, but with secial enumeration)
const int GLOBAL_CONST_VAR = 0xFF; // it is the best
extern const int GLOBAL_CONST_VAR; //some compiller doesn't understand this
C ++ 17 inline
변수
This awesome C++17 feature allow us to:
- conveniently use just a single memory address for each constant
- store it as a
constexpr
: How to declare constexpr extern? - do it in a single line from one header
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
Compile and run:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
See also: How do inline variables work?
C++ standard on inline variables
The C++ standard guarantees that the addresses will be the same. C++17 N4659 standard draft 10.1.6 "The inline specifier":
6 An inline function or variable with external linkage shall have the same address in all translation units.
cppreference https://en.cppreference.com/w/cpp/language/inline explains that if static
is not given, then it has external linkage.
Inline variable implementation
We can observe how it is implemented with:
nm main.o notmain.o
which contains:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
and man nm
says about u
:
"u" The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.
so we see that there is a dedicated ELF extension for this.
Tested on GCC 7.4.0, Ubuntu 18.04.
참고URL : https://stackoverflow.com/questions/2268749/defining-global-constant-in-c
'Nice programing' 카테고리의 다른 글
좋은 Haskell 코딩 표준 (0) | 2020.10.21 |
---|---|
“구조 나 노조가 아닌 구성원 '*******'에 대한 요청”은 무엇을 의미합니까? (0) | 2020.10.21 |
JavaScript 정규식 패턴은 변수와 연결 (0) | 2020.10.21 |
Windows Azure : Blob 컨테이너에서 하위 디렉터리를 만드는 방법 (0) | 2020.10.20 |
scipy.interpolate가 입력 범위를 초과하는 외삽 결과를 제공하도록 만드는 방법은 무엇입니까? (0) | 2020.10.20 |