C ++에서 "const"는 몇 개나 어떤 것입니까?


129

초보자 C ++ 프로그래머로서 여전히 나에게 매우 모호한 구조가 const있습니다. 당신은 너무 많은 곳에서 초보자가 살아 나오기에는 거의 불가능한 많은 다른 효과로 그것을 사용할 수 있습니다. 일부 C ++ 전문가는 다양한 용도와 사용 여부 및 / 또는 사용하지 않는 이유를 영원히 설명 할 수 있습니까?


정확히 그 질문을 찾고 : D
alamin

답변:


100

몇 가지 용도를 모 으려고합니다.

수명을 연장하기 위해 일부를 참조에 고정으로 바인딩합니다. 참조는 기본이 될 수 있으며 소멸자는 가상 일 필요는 없습니다. 올바른 소멸자는 여전히 다음과 같이 불립니다.

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

코드를 사용한 설명 :

struct ScopeGuard { 
    ~ScopeGuard() { } // not virtual
};

template<typename T> struct Derived : ScopeGuard { 
    T t; 
    Derived(T t):t(t) { }
    ~Derived() {
        t(); // call function
    }
};

template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }

이 트릭은 Alexandrescu의 ScopeGuard 유틸리티 클래스에서 사용됩니다. 임시가 범위를 벗어나면 Derived의 소멸자가 올바르게 호출됩니다. 위의 코드는 작은 세부 사항을 그리워하지만 큰 문제입니다.


const를 사용하여 다른 메소드가이 오브젝트의 논리적 상태를 변경하지 않도록하십시오.

struct SmartPtr {
    int getCopies() const { return mCopiesMade; }
};

copy-on-write 클래스에 const를 사용 하여 컴파일러 가 복사 할시기와 시기를 결정할 수 있도록합니다.

struct MyString {
    char * getData() { /* copy: caller might write */ return mData; }
    char const* getData() const { return mData; }
};

설명 : 원본과 사본의 데이터가 동일하게 유지되는 한 무언가를 복사 할 때 데이터를 공유 할 수 있습니다. 개체 중 하나가 데이터를 변경하면 이제 원본과 복사본의 두 가지 버전이 필요합니다. 즉,이다 복사 A의 쓰기 그들은 지금 모두 자신의 버전이 너무 어느 객체.

코드 사용 :

int main() {
    string const a = "1234";
    string const b = a;
    // outputs the same address for COW strings
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

위의 스 니펫은 사용 된 C ++ 라이브러리가 copy-on-write를 구현하기 때문에 GCC에 동일한 주소를 인쇄합니다 std::string. 두 문자열은 별개의 객체이지만 문자열 데이터에 대해 동일한 메모리를 공유합니다. b비 콘스탄트를 만드는 것은 비 콘스탄트 버전을 선호 operator[]하고 GCC는 백업 메모리 버퍼의 사본을 생성합니다. 우리는이를 변경할 수 있고 데이터에 영향을 미치지 않아야합니다 a!

int main() {
    string const a = "1234";
    string b = a;
    // outputs different addresses!
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

복사 생성자가 const 객체와 임시에서 복사를 수행하려면 다음을 수행하십시오 .

struct MyClass {
    MyClass(MyClass const& that) { /* make copy of that */ }
};

사소하게 변경할 수없는 상수를 만들기 위해

double const PI = 3.1415;

값이 아닌 참조를 통해 임의의 객체를 전달하는 경우 - 이 비싸거나 불가능한 값을 전달하지 않도록

void PrintIt(Object const& obj) {
    // ...
}

2
예제에서 첫 번째와 세 번째 사용법을 설명해 주시겠습니까?
tunnuz 2018 년

"파라미터가 NULL이 될 수 없음을 보장하기 위해"const가 해당 예제와 어떤 관련이 있는지 알 수 없습니다.
로건 카파도

죄송합니다. 어떻게 든 참조에 대해 쓰기 시작했습니다. 신음 해 주셔서 감사합니다 :) 물론 지금 그 물건을 제거
하겠습니다

3
첫 번째 예를 설명하십시오. 나에게는별로 이해가되지 않습니다.
chikuba

28

C ++에는 const의 두 가지 주요 용도가 있습니다.

상수 값

값이 수명 동안 변경되지 않거나 변경되지 않아야하는 변수, 멤버 또는 매개 변수의 형식 인 경우 const로 표시해야합니다. 이것은 객체의 돌연변이를 방지하는 데 도움이됩니다. 예를 들어 다음 함수에서 전달 된 Student 인스턴스를 변경할 필요가 없으므로 const로 표시합니다.

void PrintStudent(const Student& student) {
  cout << student.GetName();
}

왜 당신이 이것을 할 것입니다. 기본 데이터를 변경할 수 없다는 것을 알고 있으면 알고리즘에 대해 추론하기가 훨씬 쉽습니다. "const"는 도움이되지만 이것이 달성 될 것이라고 보장하지는 않습니다.

분명히, cout으로 데이터를 인쇄하는 데는 많은 생각이 필요하지 않습니다. :)

멤버 메소드를 const로 표시

이전 예제에서 Student를 const로 표시했습니다. 그러나 C ++은 학생에서 GetName () 메소드를 호출하면 객체가 변경되지 않는다는 것을 어떻게 알았습니까? 그 대답은 그 방법이 const로 표시되었다는 것입니다.

class Student {
  public:
    string GetName() const { ... }
};

메소드를 "const"로 표시하면 두 가지 작업이 수행됩니다. 주로 C ++ 에이 방법으로 객체를 변경하지 않는다고 알려줍니다. 두 번째는 모든 멤버 변수가 마치 const로 표시된 것처럼 취급된다는 것입니다. 이것은 클래스의 인스턴스를 수정하는 데 도움이되지만 막지는 않습니다.

이것은 매우 간단한 예이지만 질문에 대답하는 데 도움이되기를 바랍니다.


16

이 4 가지 선언의 차이점을 이해하도록주의하십시오.

다음 두 선언은 의미 상 동일합니다. 당신은 변경할 수 있습니다 CCP1 및 CCP2 점을,하지만 당신은 그들이 가리키는있는 일을 변경할 수 없습니다.

const char* ccp1;
char const* ccp2;

다음으로 포인터는 const이므로 의미가 있으려면 무언가를 가리 키도록 초기화해야합니다. 다른 것을 가리킬 수는 없지만 가리키는 것은 바꿀 있습니다.

char* const cpc = &something_possibly_not_const;

마지막으로, 우리는 두 가지를 결합하여 가리키는 대상을 수정할 수 없으며 포인터가 다른 곳을 가리킬 수 없습니다.

const char* const ccpc = &const_obj;

시계 방향의 나선 규칙은 선언을 풀도록 도와줍니다 http://c-faq.com/decl/spiral.anderson.html


로터리 방식으로 그렇습니다! 시계 방향 나선 규칙은 이름 (kpPointer)에서 시작하여 토큰을 통과하는 시계 방향 나선을 그려 각 토큰을 말합니다. 분명히 kpPointer의 오른쪽에는 아무것도 없지만 여전히 작동합니다.
Steve Folly

3

약간의 참고로, 여기서 읽은 것처럼 ,

const 왼쪽에있는 모든 것에 적용됩니다 (어떤 경우에도 오른쪽에있는 것에 적용되는 경우 제외).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.