밑에서 const에 대한 글이 있어서, 제가 일단 이해하고 있는 const에 대해서 정리해서 적어봤습니다.
다만 시간 관계상 대부분의 사람들이 알고 있는 함수의 인자로 넘기는 const보다 리턴값에서의 const의 사용을 일부 적어볼까 합니다.
분명 이것은 틀릴수도 있습니다. 틀린부분이 있다면 지적해 주시면 감사하겠습니다.

다음과 같은 클래스가 있습니다.

class MyClass
{
private:
        int m_Item;
public:
        int getItem(void);
public:
        MyClass(void);
};

MyClass::MyClass(void)
{
        m_Item = 0;
}

int MyClass::getItem(void)
{
        return m_Item;
}

위의 클래스는 안에 private 맴버변수를 하나 가지고, 생성자가 그것을 간단히 초기화 하고 있으며, 그 값을 가져오는 맴버함수를 가지고 있습니다.
그럼 간단히 써보겠습니다.

int main()
{
        MyClass test;

        int iItem = test.getItem();

        std::cout << iItem << std::endl;

        return 0;
}




출력하면 0이라는 값을 출력합니다. 하지만 맴버 변수가 int형이 아닌 여러개의 값을 가지는 구조체면 그 값을 가져올때는 어떻게 해야 할까요?

typedef struct _MyStruct
{
        int m_Int;
        float m_Float;
} MyStruct;

class MyClass
{
private:
        MyStruct m_Item;
public:
        MyStruct getItem(void);
public:
        MyClass(void);
};

MyClass::MyClass(void)
{
        m_Item.m_Int = 0;
        m_Item.m_Float = 1.0f;
}

MyStruct MyClass::getItem(void)
{
        return m_Item;
}

분명 이렇게 하기에는 무리가 있습니다. struct의 크기는 어떻게 정의하느냐에 따라서 가변적이기도 하면서 대용량의 구조를 가질수 있기 때문에 복사방식의 값의 전달에는 많은 불필요한 자원 낭비가 소모되기 때문입니다.
그렇기 때문에 참조 또는 포인터를 통해 그 값을 전달받게 되는 것이죠.

typedef struct _MyStruct
{
        int m_Int;
        float m_Float;
} MyStruct;

class MyClass
{
private:
        MyStruct m_Item;
public:
        MyStruct* getItem(void);
public:
        MyClass(void);
};

MyClass::MyClass(void)
{
        m_Item.m_Int = 0;
        m_Item.m_Float = 1.0f;
}

MyStruct* MyClass::getItem(void)
{
        return &m_Item;
}

포인터는 무조건 32비트의 크기를 가지기 때문에 (윈도우 XP에서의 기준. 윈도우 롱혼에서는 64비트로 확장되겠지요) 이렇게 하면 구조체의 크기에 상관없이 부담없이 그 값을 전달받을수 있게 됩니다. 하지만 이 방법은 새로운 문제점을 가지게 되었습니다. 포인터라는 무시무시한 C에서의 기능이 오히려 독이 된 것이지요.
만약에 다음과 같이 그 값을 전달 받았다고 해봅시다.

MyClass test;
MyStruct* Item = test.getItem();

Item으로 그 구조체의 포인터 값을 받았습니다. 하지만 이 Item이라는 포인터로 private 속성의 맴버 변수를 외부에서도 바꿀수 있게 되버립니다. 다음과 같이 말이죠...

Item->m_Int = 2;

이 것은 클래스의 private의 속성과 protect의 속성과 public의 속성을 완전히 무시하는 처사가 되어버립니다. 맴버 변수가 protect이거나 private에 상관없이 무조건 public처럼 되어버립니다.
포이터라는 기능이 클래스 설계자의 의도를 무시하는 처사가 되어버린거죠.

그것을 막기 위해 const를 사용합니다.

typedef struct _MyStruct
{
        int m_Int;
        float m_Float;
} MyStruct;

class MyClass
{
private:
        MyStruct m_Item;
public:
        const MyStruct* getItem(void);
public:
        MyClass(void);
};

MyClass::MyClass(void)
{
        m_Item.m_Int = 0;
        m_Item.m_Float = 1.0f;
}

const MyStruct* MyClass::getItem(void)
{
        return &m_Item;
}

그럼 한번 값을 바꾸어 볼까요?

MyClass test;
const MyStruct* Item = test.getItem(); // const를 사용하지 않으면 타입변환 에러가 납니다.
Item->m_Int = 2; // const 접근 에러

이렇게 해서 의도적은 포인터에 의한 접근의 제한을 막을수 있게 됩니다.


하지만 이것들은 사용자에게 값을 가져오고 싶으면 const의 선언을 무조건 사용해라 라고 강조하는 것 같습니다.
그렇기 때문에 보통 이러한 구조체의 값을 가져올때는 인자의 포인터로 받는 경우가 많습니다.

void MyClass::getItem(MyStruct* pOut)

이렇게 해서 포인터로 받아 그 값을 채워서 넘겨주는 겁니다.


실은 저도 리턴값의 const는 잘 사용하는 편은 아닙니다. 인자 전달의 const는 많이 써봤지만요.. 그렇기 때문에 요즘 const의 사용얘기가 많이 나오는 것 같아 막연히나마 알고있던 리턴값의 const의 사용을 직접 컴파일 해보면서 이것저것 해보고 이해한 바를 올려봅니다. 틀린 부분은 지적해주시면 매우 감사하겠습니다.