일지

Effective C++...2

niamdank 2022. 5. 30. 08:51

포인터의 상수 처리

포인터는 const를 어디에 붙이는지에 따라 포인터를 상수 처리할지, 데이터를 상수 처리할지 달라진다.


char greeting[] = "Hello";

char* p = greeting; // 비상수 포인터, 비상수 데이터

const char* p = greeting; // 비상수 포인터, 상수 데이터

char* const p = greeting; // 상수 포인터, 비상수 데이터

const char* const p = greeting; // 상수 포인터, 상수 데이터


 

※ 값의 수정이 필요한 경우가 아니면 const를 붙여두면 추후 실수를 막을 수 있다.

 

 

상수 함수의 오버로딩

클래스의 함수는 상수 여부만으로 오버 로딩이 가능하다.


class TextBlock {

public:

    ...

    const char& operator[] (std::size_t position) const

    { return text[position]; }

    char& operator[] (std::size_t position)

    { return text[position]; }

private:

    std::string text;

}



논리적 상수성

함수 내부적으로 상수성이 지켜지지 않더라도 사용자 측에서 알아채지 못하면 상수로 인정한다는 개념이다.


class CTextBlock {

public:

    std::size_t length() const;

private:

    char* pText;

    mutable std::size_t textLength; // mutable 선언으로 상수 처리를 회피한다.

    mutable bool lengthIsValid;

}

 

std::size_t CTextBlock::length() const

{

    if (!lengthIsValid) {

        textLength = std::strlen(pText); // 상수 함수 내부에서 의미 있는 처리가 진행될 수 있다.

        lengthIsValid = true;

    }

    return textLength;

}


다만 mutable을 이용한 상수 함수를 생성하면 비상수 함수와 동일한 기능을 수행하는 중복이 발생할 수 있다.

이때, 비상수 함수에서 상수 함수를 호출하는 식으로 처리하면 코드 중복을 막을 수 있다.

 


char& operator[](std::size_t position)

{

    return const_cast<char&> (

        static_cast<const TextBlock&>(*this)[position]; // 상수 버전 호출

    );

}


 

※ 상수 함수에서 비상수 함수를 호출하는 것은 값을 바꿀 수 있는 위험이 있으므로 하면 안 된다.