C++ 상수 (Constant)

2021. 3. 10. 21:01·SW개발/C++
목차
  1. Literal constant
  2. Symbolic constant
  3. 매크로
  4. const_cast
  5. 클래스에서의 const
  6. 클래스를 const로 인스턴스화 (instanciation)
  7. 함수 파라미터에 const와 레퍼런스를 같이 붙이는 이유
반응형

상수 (Constant)

Literal constant

  • 숫자, 문자 등 메모리에 존재하지 않아도 사용 가능한 값

  • Binary Literal

    • C++14

      0b1011'1111'1010

Symbolic constant

  • Compile Time constant

    • 컴파일할 때 값이 결정되는 상수

    • constexpr

      • C++11

      • 컴파일 타임에 값이 결정되는 상수에만 사용 가능한 키워드이다.

  • Runtime constant

    • 런타임에 값이 결정되는 상수

매크로

  • C 스타일에서는 상수를 매크로로 정의했지만, C++에서는 그렇게 사용하지 않는다고 한다.

    • 이유

      • 디버깅이 귀찮아진다.

      • 적용 범위가 너무 넓다.

    • 대신에 함수 내에서 const 형식으로 작성하는 것이 일반적이라고 한다.


const_cast

  • const로 지정한 상수의 값을 변경할 때 사용한다.

    #include <iostream>
    
    int     main()
    {
      using namespace std;
    
      const double gravity{ 9.8 };
    
      double* temp = const_cast<double*>(&gravity);
      cout << &gravity << ' ' << temp << endl;
    
      *temp = 123.0;
    
      cout << &gravity << ' ' << temp << endl;
      cout << gravity << ' ' << *temp << endl;
    }
    
    /* stdout stderr
    000DDFC84 00DDFC84
    00DDFC84 00DDFC84
    9.8 123
    */
    • 같은 주소를 사용하는데 다른 값이 나온다...

    • memcpy 함수를 사용해도 변하지 않는다.

      #include <iostream>
      
      int     main()
      {
        using namespace std;
      
        const double gravity{ 9.8 };
      
        cout << gravity << endl;  // 9.8
      
        const double temp = 1024.0;
      
        memcpy(const_cast<double*>(&gravity), &temp, sizeof(double));
      
        cout << gravity << endl;  // 9.8
      }
      
      /* stdout stderr
      9.8
      9.8
      */
    • 이렇게 사용하지 않는게 좋을 것 같다.


클래스에서의 const

클래스를 const로 인스턴스화 (instanciation)

  • 멤버 함수를 정의할 때, 값을 변경하지 않는 함수면 컴파일러가 알 수 있도록 함수 정의 시 const 키워드를 붙이는게 좋다.

  • 멤버 변수들을 수정할 수 없다. 모두 const 취급하는 것이다.

    int    getValue() const
    {
      return value_;
    }

함수 파라미터에 const와 레퍼런스를 같이 붙이는 이유

  • 다음 예제에서 print 함수의 파라미터는 복사 생성자를 호출한다.

    #include <iostream>
    
    class Something
    {
      int value_ = 0;
    
    public:
      Something()
      {
        std::cout << "Constructor\n";
      }
    
      int    getValue() const
      { 
        return value_;
      }
    };
    
    void    print(Something s)
    {
      std::cout << &s << std::endl;
      std::cout << s.getValue() << std::endl;
    }
    
    int        main()
    {
      const Something s;
    
      std::cout << &s << std::endl;
      print(s);
    }
    
    /* stdout
    Constructor
    012FFB9C
    012FFAC8
    0
    */
    • "Constructor" 메시지가 한 번만 출력된 것을 볼 수 있다.

      • 위에 정의된 생성자가 아닌, 기본 복사 생성자를 호출했기 때문이다.
  • 이렇게 복사하는건 오버헤드가 크기 때문에 다음과 같이 원본으로 가져오는게 일반적이다.

    #include <iostream>
    
    class Something
    {
      int value_ = 0;
    
    public:
      Something()
      {
        std::cout << "Constructor\n";
      }
    
      int    getValue() const
      { 
        return value_;
      }
    };
    
    void    print(const Something& s)
    {
      std::cout << &s << std::endl;
      std::cout << s.getValue() << std::endl;
    }
    
    int        main()
    {
      const Something s;
    
      std::cout << &s << std::endl;
      print(s);
    }
    
    /* stdout
    Constructor
    00AFFB78
    00AFFB78
    0
    */
  • const 키워드 유무에 따라 오버로딩이 다르게 적용된다.

    • 원래 같은 파라미터를 갖는 같은 이름의 함수는 두 개 이상 정의할 수 없으나, const가 붙는 함수는 다른 함수 취급한다.

      #include <iostream>
      
      class Something
      {
          int value_ = 0;
      
      public:
          const int& getValue() const
          {
              std::cout << "const version : " << value_ << '\n';
              return value_;
          }
      
          int& getValue()
          {
              std::cout << "non-const version : " << value_ << '\n';
              return value_;
          }
      };
      
      int        main()
      {
          Something       s1;
          const Something s2;
      
          s2.getValue();
          s1.getValue() = 100;
          s1.getValue();
      }
      
      /* stdout
      const version : 0
      non-const version : 0
      non-const version : 100
      */
    • 다음과 같이 const를 빼고 getValue 함수를 작성하면 오버로딩 오류가 발생한다.

      public:
      const int&    getValue()  // 여기 const가 없으면 오류
      { 
        std::cout << "const version : " << value_ << '\n';
        return value_;
      }
      
      int&        getValue()
      {
        std::cout << "non-const version : " << value_ << '\n';
        return value_;
      }
      error C2556: 'int &Something::getValue(void)': overloaded function differs only by return type from 'const int &Something::getValue(void)'
    • 다음과 같이 반환 값에 const가 없어도 오류가 발생한다.

      int&    getValue() const
      { 
        std::cout << "const version : " << value_ << '\n';
        return value_;
      }
      error C2440: 'return': cannot convert from 'const int' to 'int &'
      • int& getValue() const에서 오른쪽 const에 의해 내부 변수 값들이 const 취급된다. (여기서는 const int)

      • 그런데 반환 값은 int& 형태의 레퍼런스이므로 자료형이 맞지 않아서 발생하는 오류이다.

      • 반환 자료형을 레퍼런스 없이 int로만 쓰면 오류는 없지만, 앞에도 const를 붙여주는게 맞는 것 같다.

반응형
저작자표시 (새창열림)

'SW개발 > C++' 카테고리의 다른 글

C++ 산술 연산자 (Arithmetic Operator)  (0) 2021.03.10
따라하며 배우는 C++ 3장  (0) 2021.03.10
C++ 출력 버퍼 비우기  (0) 2021.03.10
C++ 형 변환 (Type Casting)  (0) 2021.03.09
C++ Boolean  (0) 2021.03.09
  1. Literal constant
  2. Symbolic constant
  3. 매크로
  4. const_cast
  5. 클래스에서의 const
  6. 클래스를 const로 인스턴스화 (instanciation)
  7. 함수 파라미터에 const와 레퍼런스를 같이 붙이는 이유
'SW개발/C++' 카테고리의 다른 글
  • C++ 산술 연산자 (Arithmetic Operator)
  • 따라하며 배우는 C++ 3장
  • C++ 출력 버퍼 비우기
  • C++ 형 변환 (Type Casting)
Caniro
Caniro
MinimalismCaniro 님의 블로그입니다.
  • Caniro
    Minimalism
    Caniro
  • 전체
    오늘
    어제
    • 전체보기 (319)
      • SW개발 (268)
        • Java Spring (6)
        • C++ (186)
        • Python (21)
        • Linux (16)
        • 알고리즘 (13)
        • Git (4)
        • Embedded (1)
        • Raspberrypi (9)
        • React (3)
        • Web (2)
        • Windows Device Driver (6)
      • IT(개발아님) (46)
        • Windows (26)
        • MacOS (7)
        • Utility (11)
      • 챗봇 짬통 (0)
      • 일상 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    dism
    Windows 11
    logi options
    로지텍 마우스 제스처
    windows
    spring
    윈도우 명령어
    unix
    java
    그림판
    제외
    Solaris 10
    백기선
    MacOS
    vscode
    mspaint
    SunOS 5.1
    스프링 프레임워크 핵심 기술
    맥북 카카오톡 알림 안뜸
    윈도우
    citrix workspace
    시스템 복구
    KakaoTalk
    Workspace
    EXCLUDE
    SFC
    스프링
    알림
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Caniro
C++ 상수 (Constant)

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.