반응형
(42Seoul의 CPP01 과제를 진행하며 공부한 내용을 작성한 TIL을 정리한 글 입니다.)
함수 공부📓
new
포인터 변수명 = new 타입;
//int *ptr = new int;
포인터 변수명{new 타입};
//int *ptr{new int};
//초기화 같이 하는 방법
포인터 변수명 = new 타입(초기화 값);
//int *ptr = new int(10);
포인터 변수명{new 타입};
//int *ptr{new int(10)};
- 메모리 공간 할당하는 연산자이며, 생성자를 호출하고, 할당하고자 하는 자료형에 맞게 형 변환
- new 는 바로 초기화가 가능함
- 메모리 할당 실패 시, malloc 과는 다르게 bad_alloc 이라는 익셉션을 리턴함. try - catch 문을 사용해서 확인해야 한다.
- (23.07.28 추가) C++ 은 익셉션이 리턴될 때 try - catch 문으로 잡지 않으면, 프로그램이 종료된다는 것을 알았다. C 처럼 NULL이 할당되어 이후에 NULL로 인한 문제가 발생되지 않기 때문에, 메모리 할당 실패 시 다른 동작을 정의할 것이 아니라면 예외처리는 꼭 필요하진 않을 것 같다.
#include <iostream>
int main()
{
try
{
int *ptr = new int;
}
catch (std::bad_alloc & ba)
{
std::cerr << "bad_alloc 발생" << ba.what() << std::endl;
}
return 0;
}
- nothrow 를 사용해서 익셉션 대신 nullptr 을 리턴하도록 할 수 있음 (C++98 버전 아님)
#include <new>
#include <iostream>
int main()
{
int *ptr = new(std::nothrow) int;
if (ptr == nullptr)
std::cout << "return nullptr" << std::endl;
return 0;
}
delete
delete 포인터 변수명;
//delete ptr;
//배열은 아래처럼
//delete [] ptr;
- new로 할당한 ptr에 저장된 메모리 해제
개념 공부📓
함수 포인터와 멤버 함수 포인터
- 함수 포인터
- 함수의 주소를 저장하고 호출하는 포인터
int add (int a, int b)
{
return a + b;
}
int subtract (int a, int b)
{
return a - b;
}
int main()
{
int (*funcPtr)(int, int); //함수 포인터 선언
funcPtr = add; // add 함수를 가리키도록 초기화
int result = funcPtr(5, 3); //함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //8 출력
funcPtr = subtract; //subtract 함수를 가리키도록 초기화
result = funcPtr(5, 3); //함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //2 출력
return 0;
}
- 함수 포인터 배열
int add (int a, int b)
{
return a + b;
}
int subtract (int a, int b)
{
return a - b;
}
int main()
{
int (*funcPtr[2])(int, int); //함수 포인터 배열 선언
funcPtr[0] = add; // add 함수를 가리키도록 초기화
funcPtr[1] = subtract //subtract 함수를 가리키도록 초기화
int result = funcPtr[0](5, 3); //함수 포인터 배열을 통한 함수 호출
std::cout << result << std::endl; //8 출력
result = funcPtr[1](5, 3); //함수 포인터 배열을 통한 함수 호출
std::cout << result << std::endl; //2 출력
return 0;
}
- 멤버 함수 포인터
- 클래스의 멤버 함수의 주소를 저장하고 호출하는 포인터
- 클래스의 인스턴스를 통해 호출되어야 함
class Calculator
{
public:
int add (int a, int b)
{
return a + b;
}
int subtract (int a, int b)
{
return a - b;
}
}
int main()
{
Calculator cal;
int (Calculator::*funcPtr)(int, int); //멤버 함수 포인터 선언
funcPtr = &Calculator::add; //add 멤버 함수를 가리키도록 초기화
int result = (cal.*funcPtr)(5, 3); //멤버 함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //8 출력
funcPtr = &Calculator::subtract; //subtract 멤버 함수를 가리키도록 초기화
result = (cal.*funcPtr)(5, 3); //멤버 함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //2 출력
return 0;
}
- 멤버 함수 포인터 배열
- 함수 포인터와 멤버 함수 포인터는 다른 타입으로 취급되며 호환되지 않음
class Calculator
{
public:
int add (int a, int b)
{
return a + b;
}
int subtract (int a, int b)
{
return a - b;
}
}
int main()
{
Calculator cal;
int (Calculator::*funcPtr[2])(int, int); //멤버 함수 포인터 배열 선언
funcPtr[0] = &Calculator::add; // add 함수를 가리키도록 초기화
funcPtr[1] = &Calculator::subtract //subtract 함수를 가리키도록 초기화
int result = (cal.*funcPtr[0])(5, 3); //멤버 함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //8 출력
result = (cal.*funcPtr[1])(5, 3); //멤버 함수 포인터를 통한 함수 호출
std::cout << result << std::endl; //2 출력
return 0;
}
if/else 문 사용하지 않고 분기 처리하기
- ex05 문제에서 if/else 문을 사용하지 않고 분기하여, 멤버 함수 포인터 배열을 통해 함수를 실행 시켜야 한다.
- if/else 문을 사용하지 말라는 점이, 분기가 엄청 많아질 경우에는 if/else 문은 관리가 힘드니 사용하지 말라는 것으로 이해하여, 대안인 switch 문은 사용하지 않고 코드를 짜보려고 한다.
- complain 함수의 인자로 level이 들어오면, 그 level 에 맞는 함수를 실행시켜야 하기 때문에, levels 배열을 만들어 find 로 level 을 찾고, 그 인덱스를 사용하여 멤버 함수 포인터 배열에서 함수를 실행시킨다.
void Harl::complain(std::string level)
{
typedef void (Harl::*funcPtr_t)();
funcPtr_t funcPtr[4] = {&Harl::debug, &Harl::info, &Harl::warning, &Harl::error};
std::string levels[4] = {"debug", "info", "warning", "error"};
(this->*funcPtr[levels->find(level)])();
}
- 이렇게 했더니, 유효하지 않는 level 이 들어왔을 때, find 함수에서 std::string::npos를 반환하기 때문에 segfault 에러가 발생한다,, 예외처리를 위해서라도 switch 문을 사용하는게 최선일 것 같다.
제가 공부한 내용을 기록하고 있습니다.
혹시 수정이 필요한 부분이 있다면, 댓글로 지적 부탁드립니다!
선한 관심과 도움 감사드립니다😊
반응형
'C++' 카테고리의 다른 글
[C++] 42SEOUL CPP04 개념 공부하기 (0) | 2023.07.28 |
---|---|
[C++] 42SEOUL CPP03 개념 공부하기 (0) | 2023.07.28 |
[C++] 42SEOUL CPP02 개념 공부하기 (0) | 2023.07.28 |