Oh-My-C-P-P 01
개인적으로 공부한 C++ 내용을 공유합니다.
Hello World!
#include <iostream>
int main()
{
std::cout << "Hello, World!!!" << std::endl;
return (0);
}
iostream
헤더는 C++의 표준 입출력을 포함하고 있습니다.
std::cout
은 무언가를 출력시켜주는 것이고
std::endl
은 한줄 엔터를 쳐서 나타내라는 표시 즉, 개행을 나타냅니다.
여기서 std::
에서 std
는 C++ 표준 라이브러리의 모든 함수 객체 등이 정의된 이름 공간(namespace)입니다.
이름 공간 이란, 어떤 정의된 객체에 대해 어디 소속인지 지정해주는 것을 나타냅니다. 코드의 크기 늘어나거나 다른 사람들이 쓴 코드를 가져다 쓰는 경우가 많아지면서 중복된 이름을 가진 함수들이 많아지게되는데, C++ 에서는 이를 구분하기 위해 같은 이름이라도 소속된 이름 공간이 다르면 다른 것으로 취급하도록 했습니다.
namespace header1 {
int foo();
void bar();
}
namespace header2 {
int foo();
void bar();
}
위와 같은 예시가 있을 때, header1.h
과 header2.h
를 모두 include
한다면, header1::foo()
, header2::foo()
와 같이 각각의 네임스페이스를 붙여 같은 이름의 함수를 쓸 수 있습니다.
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, World!!!" << endl;
return (0);
}
위와 같이 using namespace std;
를 사용하여 어떠한 이름 공간을 사용하겠다고 선언을 할 수 있는데 이는 권장되지 않습니다. 그 이유는 std
에 이름이 겹치는 함수를 만들게 된다면, 오류가 발생하기 때문입니다. 따라서 혹시 모를 충돌을 위해 사용하지 않는 것을 권장합니다.
namespace {
int a;
int test() {}
}
위에 처럼 하나의 파일 안에 namespace
를 이름을 정하지 않고 구성하여 변수나 함수를 정의했다고 했을 때 현재 파일에서는 a
와 test
앞에 특정 namespace::
를 사용하지 않더라도 사용할 수 있다. 하지만 다른 파일에서는 a
와 test
를 접근할 수 없다. 이는 static
처럼 선언한 것과 같이 특정 파일 내에서만 사용할 수 있도록 된 것임을 나타낸다.
C와 C++은 친구
C와 C++은 if, else, switch, for, while, break, continue
등등 기본적인 문법 구조가 똑같다. 따라서 C에서 사용했던 것과 동일하게 문법을 사용하면 된다. 또한 C에서 되던 것은 C++ 에서 거의 100% 된다고 봐도 무방하다.
참조자 도입
참조자는 특정 변수의 별명을 말한다. 즉 별명을 이용해서 한 변수를 나타내는 변수를 여러개 만드는 것이다.
#include <iostream>
int main()
{
int a = 3;
int& another_a = a;
another_a = 5;
std::cout << "a : " << a << std::endl;
std::cout << "another_a : " << another_a << std::endl;
return (0);
}
참조자는 선언과 동시에 누구의 별명이 될 것인지 같이 선언해주어야한다.
참조자를 정하는 방법은 가리키고자 하는 타입 뒤에 &를 붙이면 된다.
참조자는 메모리 상에 공간을 할당하지 않고 별명으로 가리키려는 변수의 메모리를 같이 사용한다.
참조자의 참조자 타입은 금지되어 있으며 참조자의 참조자를 사용하려면 참조자를 참조자의 타입으로 받으면 된다.
// 문제의 코드
int main()
{
int a = 3;
int& another_a;
return (0);
}
상수와 같은 코드상의 값을 리터럴이라고 하는데 const
형의 참조자를 사용하면 리터럴 또한 상수 참조자로 참조할 수 있다.
참조자는 배열로 선언할 수 없는데, 그 이유는 배열이 되기위해선 주소값이 존재해야하는데 참조자는 메모리상에 존재하지 않기 때문이다. 이러한 모순 때문에 선언할 수 없다.
하지만 다음과 같이 배열의 크기를 명시하여 각각의 배열의 값을 참조자로 선언할 수 있다.
int arr[3] = {1, 2, 3};
int (&ref)[3] = arr;
이렇게 되면 ref[0]
부터 res[2]
가 각각 arr[0]
부터 arr[2]
의 레퍼런스가 된다.
다음과 같이 2차원 배열도 가능하다.
int arr[3][2] = {1, 2, 3, 4, 5, 6};
int (&ref)[3][2] = arr;
참조자를 사용할 때 주의해야 할 점이 하나 더 있는데, 레퍼런스를 리턴하는 함수에서 지역 변수의 레퍼런스를 리턴하지 않도록 조심해야 한다는 점이다. 지역변수는 그 함수가 끝나면 사라지므로 그 지역변수를 레퍼런스하고 있는 참조자는 잘못된 영역의 접근을 하게 된다. 이것을 댕글링 레퍼런스(Dangling reference)라고한다.