공부/C || C++ 43

네임스페이스(namespace)란? std란?

C++을 맨 처음 배울 때 기계처럼 치던 코드중 하나가 using namespace std;였다. 그때 당시 이 코드 한줄이면 cout을 사용할 때 불편하게 std::를 붙이지 않아도 돼서 무조건 썼는데 사실 현업에선 이렇게 쓰지 않는다는 이야기를 듣고 쓰지 않도록 노력하고 있다. 그런데 문득 namespace와 std는 어떤걸 의미하는지 궁금해졌다. 우선 namespace는 어떤 변수나 함수의 소속을 알려주는 기능을 한다. 예를 들어서 #include namespace A { int Num = 100; } namespace B { int Num = 200; } using namespace A; using namespace B; int main() { int Num = 300; std::cout

공부/C || C++ 2021.07.19

C++ 대입 연산자는 왜 void로 선언하면 안될까? 반환 타입에 왜 참조자를 붙여야 할까?

class AAA { public: int x; int y; public: AAA(int _x, int _y) : x(_x), y(_y) {}; } 위와 같은 클래스가 있을 때 대입 연산자를 어떻게 작성할까? 대부분 아래와 같이 작성 할것이다. AAA& operator=(const& AAA aaa) { x = aaa.x; y = aaa.y; return *this; } 여기서 의문점이 드는것은 두가지였다. 첫번째는 그냥 대입만 하면 되니까 void 리턴 타입으로 하면 되지 않을까? 였다. 첫번째 의문은 나와같은 의문을 가진 사람의 stackoverflow 질문에 대한 답변에서 찾을 수 있었다. 결론부터 이야기하면 void 리턴타입으로 대입 연산자를 만드는게 가능은 하지만, 그렇게 하면 A = B = C같..

공부/C || C++ 2021.07.18

C++11 chrono

프로그램을 작성하다 보면 두가지 기능의 성능을 비교할 때 초단위로 혹은 그보다 정밀한 단위로 시간을 측정해야할 경우가 있다. C++ 11에서는 chrono 라이브러리에서 nanosecond단위의 시간 측정을 지원한다. 예를 들어서 피보나치 수열 함수를 동작하는데 걸리는 시간을 second, millisecond 그리고 nanosecond 단위로 측정해보자. #include #include long fibonacci(unsigned n) { if (n < 2) return n; return fibonacci(n - 1) + fibonacci(n - 2); } int main() { auto start = std::chrono::high_resolution_clock::now(); fibonacci(40);..

공부/C || C++ 2021.07.16

C++ 11 default, delete 키워드

C++ 11에서는 자체적으로 선언하지 않을 경우 기본 생성자, 복사 생성자, 복사 할당 연산자 및 소멸자를 자동으로 생성하고 이러한 함수는 특수 멤버 함수 라고 한다. 이런 특수 멤버 함수에는 몇가지 규칙이 있다(아래 규칙들은 microsoft docs에 있는걸 가져왔다). 생성자가 명시적으로 선언된 경우 기본 생성자가 자동으로 생성되지 않습니다. 가상 소멸자가 명시적으로 선언된 경우 기본 소멸자가 자동으로 생성되지 않습니다. 이동 생성자 혹은 이동 할당 연산자가 명시적으로 선언된 경우 다음과 같습니다. 복사 생성자가 자동으로 생성되지 않습니다. 복사 할당 연산자가 자동으로 생성되지 않습니다. 복사 생성자, 복사 할당 연산자, 이동 생성자, 이동 할당 연산자 또는 소멸자가 명시적으로 선언된 경우 다음과 ..

공부/C || C++ 2021.07.15

C++ 11 enum class

C++ 11부터는 enum class라는 syntax를 지원한다. 이 enum class는 기존의 enum의 문제점을 보완하고자 나온 syntax이다. enum은 사용자 정의 타입임에도 정수형과 호환이 가능하다. 예를 들어서 enum Color { RED, GREEN, BLUE }; int main() { int rgb = RED; } 또한 enum은 정의하면 enum내에서가 아닌 enum이 포함된 스코프 내에서 정의되기 때문에 같은 스코프 내에서 서로 다른 enum 블록에서 정의한다고 하더라도 이름이 겹치면 재정의된 것으로 보고 오류가 난다. 예를 들어서 int main() { enum Color { RED, BLUE, GREEN, // duplicated! }; enum Color2 { GREEN, ..

공부/C || C++ 2021.07.10

char*를 cout으로 출력할 경우 주소가 올바르게 나오지 않는 경우

reinterpret_cast를 이용해서 int*를 char*로 cast해서 주솟값을 std::cout을 이용해서 확인해보니 주솟값이 출력이 안되는 경우가 있었다. 처음엔 reinterpret_cast에 대해서 내가 잘 모르는게 있는줄 알고 열심히 찾아봤는데 그게 아니고 헤더 중에서도 출력과 관련 있는 에 대해 내가 모르는게 있었다. C++에서 을 이용해서 아래 코드처럼 char*의 주솟값을 출력하려고 하면 아무것도 출력되지 않는다. int memory[10]{ 1,2,3,4,5,6,7,8,9,10 }; int main() { int* p = memory; char* c = reinterpret_cast(p); cout

공부/C || C++ 2021.07.09

C++ 전처리기(preprocessor)

전처리기란 컴파일 전에 실행되는 코드로써 #으로 시작한다. 종류로는 include, Macro 그리고 조건부 컴파일(Conditional compilation)이 있다. 1. include 다들 알다시피 컴파일러와 함께 제공되는 헤더파일은 를 이용해서 포함시키고, 따로 사용자가 작성한 헤더파일은 소스코드가 있는 경로 기준으로 해서 ""를 이용해서 포함시킨다. 예를 들어서 아래와 같다. #include // 컴파일러에서 제공되는 헤더파일 #include "MemoryBlock.h" // 사용자 정의 헤더파일 2. Macro Macro에는 #define을 이용해서 만들고 종류는 객체와 유사한 매크로와 함수와 유사한 매크로가 있다. 객체와 유사한 매크로는 다시 대체 텍스트가 있는 것과 없는 것으로 나뉘는데 예..

공부/C || C++ 2021.07.08

C+ 11 스마트 포인터(unique_ptr, shared_ptr, weak_ptr)

C++는 JAVA와 달리 가비지 컬렉터가 없기 때문에 new로 메모리 할당을 하고 사용이 끝나면 사용자가 반드시 delete로 해제해줘야 한다. 하지만 스마트 포인터는 포인터처럼 동작하는 클래스 템플릿으로써, 할당 후 메모리 해제를 해주지 않아도 자동으로 해제해주는 기능을 가진 녀석이다. 더 정확하게 이야기하면 스마트 포인터라는 클래스 템플릿의 소멸자에는 사용한 자원을 해제해주는 코드가 포함되어 있다고 한다. 이러면 자연스럽게 메모리 할당 후 해제를 해주지 않아서 생기는 memory leak도 어느 정도 해결될 것이라고 생각한다. 신기하게 new로 할당한 메모리도 스마트 포인터에 대입하면 나중에 해제해주지 않아도 된다고 한다. 스마트 포인터에는 unique_ptr, shared_ptr, weak_ptr ..

공부/C || C++ 2021.07.07

C++ 오버로딩(overloading) vs 오버라이딩(overriding), 가상함수(virtual function) 그리고 다형성(polymorphism)

C++을 공부한 사람이라면 누구나 한번쯤은 헷갈려 봤을 법한 오버로딩과 오버라이딩에 대해 정리해보자. 우선 오버로딩은 매우 간단하다. 함수 파라미터 타입이나 갯수만 다르게해서 다른 함수로 인식하도록 하는 것이다. 그 말은 함수의 리턴 타입만 다르게 해서는 오버로딩이 아니라는 의미이다. 예를 들어서 이렇게 리턴 타입만 다르고 함수 파라미터의 갯수와 타입이 같으면 오버로딩이 안된다는 것이다. 오버라이딩은 상속 관계에서 부모의 기능을 자식이 상속받을 때, 자식이 부모의 기능을 재정의하는 것을 의미한다. 예를 들어서 class person { public: void foo() { cout

공부/C || C++ 2021.07.05

C 헷갈리는 char*와 char[] 그리고 string <-> char* 변환 방법

C++을 쓰면서는 string만 쓰겠지 생각하지만 은근히 char*나 char 배열을 쓰는 경우가 많다(나만 그런가). 쓰다보면 저 두개의 차이점을 잘 모르겠는데 이번 기회에 공부해서 정리해보려고 한다. 그리고 string char* 변환도 은근 자주 써야하는데 이거도 같이 정리해보자. 먼저 char*와 char array는 사이즈가 다르다 char*는 당연히 포인터니까 4byte이고, char array는 할당한 크기에 따라 달라질 것이다. 또 다른점은 char array는 인덱싱으로 해당 인덱스의 문자만 변경하는게 가능하다. int main() { char str[10] = "Hello"; str[3] = 'r'; } 하지만 char*는 똑같이 선언해도 .rodata section에 들어가는 녀석이라..

공부/C || C++ 2021.07.05