C++ 이름공간, 참조자!

이름공간(namespace)

개발 편의성을 위해 사용, 같은 이름, 같은 형, 같은 인자 개수 함수도 이름공간이 다르면 구분해서 사용 가능.

namespace FirstNameSpace
{
  void SimpleFunc()
  {
    std::cout<<FirstNameSpace SimpleFunc<<std::endl;
  }
}

namespace SecondNameSpace
{
  void SimpleFunc()
  {
    std::cout<<SecondNameSpace SimpleFunc<<std::endl;
  }
}
int main()
{
  FirstNameSpace::SimpleFunc();
  SecondNameSpace::SimpleFunc();
  //함수 이름, 매개변수 개수, 변수 형 모두 같은 상황이지만 이름 공간이 다르기 때문에 OK
  return 0;
}

사용하는 이유는 여러 개발자가 협업 하면서 개발하다 보면 함수가 서로 비슷해서 겹치는 경우가 생기는데 이를 해결하기 위해서 라고…..
사용되는 ::cout이나 cin을 사용할때 많이 보았다.
배운것 처럼 cout, cin, endl과 같은 객체들이 std라는 namespace안에 있기 때문.

using을 사용하면 귀찮은 ::을 안써도 된다.

#inlcude <iostream>

using std::cin;
using std::cout;
using std::endl;
using FirstNameSpace::SimpleFunc;
//using을 사용해서 다음부터 함수 호출 할땐 이름공간 없이 호출!

namespace FirstNameSpace
{
  void SimpleFunc()
  {
    ...
  }
}
int main()
{
  cout<<"Hello wolrd!"<<endl;
  //귀찮은 std 이름공간 생략
  SimpleFunc();
  //SimpleFunc가 소속된 이름공간도 생략
  return 0;
}
#inlcude <iostream>

using namespace std;
int main()
{
  cout<<"Hello wolrd!"<<endl;
return 0;
}

참조자(Reference)

C++에서 사용되는 포인터와 비슷한 녀석

int num1=10;
int *ptr1=num1;   //c에서 사용하는 포인터
int &num2=num1;   //이녀석이 참조자
//c에서는 볼수 없던 형식, num1에 num2라는 별명을 지어준 샘이다.

참조자는 변수와 똑같이 작동하기 때문에 변수라고 봐도 무방함.
참조자는 상수, NULL, 초기참조 대상없이는 선언 불가능. 아래처럼 하면 오류난다.

int &ref1=10;
int &ref1=NULL;
int &ref1;


c에서 call by value, call by reference 라고 들어 보았을 것인다,
함수의 매개변수가 변수 값만 받아 사용하느냐, 변수 주소값을 받아 값의 변경까지 할 수 있게 하는냐 차이다.
c++에선 포인터를 사용해 똑같이 할 수 있지만 참조자를 통해서도 할 수 있다.

void SwapByAddr(int *ptr1, int* ptr2)
{
  int temp=*ptr1;
  *ptr1=*ptr2;
  *ptr2=temp;
}
void SwapByRef(int &ref1, int &ref2)
{
  int temp=ref1;
  ref1=ref2;
  ref2=temp;
} //그냥 변수처럼 사용하면 되서 편하다.

int main()
{
  int num1=10;
  int num2=20;
  SwapByRef(num1, num2);
}

ref1이 num1의 10을 받아서 연산하는 것이 아니라 num1자체를 받기 때문에 교환이 이루어짐. 애초에 참조자는 상수 초기화가 안된다.

참조자도 물론 단점이 있다.

...
HappyFunc(num);
printf("%d", num);
...

C에서 위와같이 사용했다면 num이 어떤 변수인진 모르지만 HappyFunc안에서 num값이 변경 되지 않았다고 확실히 말 할 수 있다. 하지만 C++에선 아니다.

void HappyFunc(int &ref); //함수 선언문
...
int num;
HappyFunc(num); //num값이 안에서 바뀔수도 있음.

HappyFunc의 매개변수가 참조자로 선언되어있어 num값이 함수 안에서 변경 되지 않는지 확신할 수 없다.

개발하다 num값이 이상해 어디서 변경되는지 확일할 때 HappyFunc같이 선언된 함수가 있다면 함수 안을 모두 살펴 보아야 한다.


다행히 const를 사용하면 함수 안까지는 살펴보지 않아도 함수안에서 num이 변경되는지 안되는지 확인 할 수 있다.

void HappyFunc(const int &ref); 
//선언부만 보고 num이 벼경되지 않음을 확신
...
int num;
HappyFunc(num);

함수 원형을 보고 const를 확인하였기 때문에 HappyFunc안에서 num이 변경되지 않음을 확신할 수 있다.

반환형이 참조자일 경우

반환을 받은 변수에 따라 어떤 값이 저장될지 달라진다.

int& RefReturnFuncOne(int &ref)
{
  ref++;
  return ref;
}

int RefReturnFuncTwo(int &ref)
{
  ref++;
  return ref;
}
int main()
{
  int num=1;
  int &num2=RefReturnFuncOne(num1);
  num1++;
  num2++;
  //num1과 num2는 모두 같은 주소위치를 가르키고 있고 값은 4.

  int num3=1;
  int num4=RefReturnFuncOne(num3);
  num3++;
  num4+=100;
  //num4는 그저 int형 변수이기 때문에 num3은 참조값(주소)가 아닌 정수값을 반환받음.
  //num3은 3, num4는 102가됨.
}

RefReturnFuncTwo의 경우 반환형이 int형이기 애초에 반환값이 참조값(주소) 아닌 참조자의 값이 된다.

int &num=RefReturnFuncTwo(temp);

참조자는 상수참조자 안되기 때문에 위처럼 사용하면 컴파일 오류발생.

~생성된 임시변수를 참조하는 방식으로 가능할 줄 알았는데 어차피 임시변수는 사라지고 값만 남기 때문에 상수취급 해서 안되나봄….~


const 참조자

참조자가 상수를 참조 못한다 하였지만 const키워드를 사용하면 사실 된다….

...
int main()
{
  const int num1=10;
  int &ref1=num1; //num을 상수취급 해서 오류발생

  const int num2=10;
  const int &ref2=num2; //const키워드로 참조 가능

  const int &ref3=10; // 이것도 가능
}

10이라는 상수(리터럴상수)도 컴퓨터 특정 주소에 저장된 값이다.
다음행으로 넘어가는 순간 이 주소안의 값은 쓰레기값으로 변한다(언제든지 덮혀씌어질 수 있음).
굳이 참조까지 하면서 유지 시키려는 이류는 다음과 같다.

int Adder(const int &num1, const int &num2)
{
  return num1+num2;
}
...
cout<<Adder(3,4)<<endl;

상수도 넘기고 변수도 넘기고!

태그: ,

카테고리:

업데이트: