WN_인생기록

언리얼 C++ 면접 질문 대비 본문

C++/면접 대비

언리얼 C++ 면접 질문 대비

WhNi 2024. 7. 25. 01:48

1. const int*, int const* int* const 차이점 -> const 가 어디에 붙어있는지 물어보는 질문 

 

-> 기본적으로 const 는 상수라는 의미를 가지고 있는데, const + 변수형 + 변수이름 인 경우에는 변수이름을 가진 데이터가 변할수 없는 상수 라는 의미를 가짐.

 

-> const int* (변수명) 은 변수가 가지고 있는 데이터의 값이 상수임을 나타내는것. 그렇기 때문에 해당 포인터가 다른 변수를 가리켜도 컴파일에는 문제가 없다. 

 

-> int* const (변수명)은 포인터 자체가 상수임을 나타내는것. 그렇기 때문에 해당 포인터가 가리키고 있는 데이터의 값이 변경되어도 컴파일에는 문제가 없으나, 포인터가 가리키는 변수 자체는 변경할 수 없다. 

	int num = 3;
	int num2 = 5 ;
	int num3 = 1;

	// const int* ptr 은 다른 변수를 가리킬 수 있지만, 변수가 가리키는 값을 변경할 수는 없음. 즉 포인터가 가리키는 변수의 값이 상수라는 뜻.
	const int* ptr = #
	ptr = &num3;

	// 포인터 자체가 상수임을 나타내는것. 가리키는 데이터의 값을 변경할 수는 있지만, 포인터가 가리키는 변수 자체는 변경할 수 없음. 
	int* const ptr2 = &num2;
	num2 = 7;

이렇게 이해하면 됨.

 

 

2. C++ 11 이후 auto 키워드를 사용하는 장단점은 무엇인가 -> 모던 C++에 대한 이해

장점 -> 타입을 명시적을 선언하지 않아도 되고, 복잡한 타입을 자동으로 추론

단점-> 정말로 복잡한 타입의 경우, 명시적으로 해당 타입을 파악하기가 어려움, 컴파일러의 추론과 다른 결과가 나올수도 있음

 

3. C++ 에서 동작하는 메모리 관리가 어떻게 되는지 알고있나요? -> C++에 대한 기본적인 이해, 메모리에 대한 이해

스택은 함수 호출시 지역변수와. 함수의 매개변수가 스택에 할당되어서 자동으로 할당 및 해제되고,

힙은 동적 메모리 할당을 위해 사용되며, new 나 delete를 사용해서 명시적으로 관리해야함. 그런데 최근에는 스마트 포인터의 등장으로 자동으로 메모리 할당과 해제를 도와주는 기능이 생김

 

-> 스마트 포인터는 무엇이고 어떤게 있는가? 

스마트 포인터는 동적메모리 할당으로 인한 단점을 커버하기 위해 나온 기능입니다. 스마트 포인터의 종류는 unique_ptr, shared_ptr, weak_ptr이 있습니다. 

 

먼저 unique_ptr의 경우는 소유권이 한 객쳉에만 독점적으로 귀속되며, 해당 함수의 수명이 끝날때, 스마트 포인터의 수명도 끝이 납니다. 독점적이기 때문에 소유권의 이전은 std::move로 가능하지만 2개 이상의 포인터가 동일한 객체를 소유할 수 없습니다.

 

다음은 shared_ptr이며, 이 기능은 말그대로 소유권을 공유하며, 레퍼런스된 객체들을 카운팅하고, 그 객체들이 전부 소멸된다면 shared_ptr도 소멸됩니다. 카운팅이 0이 되는 순간 포인터가 소멸하게 된다는 점이 중요합니다. 

 

 

하지만, 2 객체가 서로를 참조하고 있는 경우 카운트가 절대 0이 되지 않으므로 순환참조 문제가 발생합니다. 때문에, weak_ptr은 이를 방지하기 위해서 나온 기능입니다. weak_ptr은 객체의 소유권을 가지지 않으며, 객체가 유효한지 확인하려면 lock()이라는 기능을 써야합니다. lock()은 참조하고 있는 객체가 유효하면 shared_ptr로 변환이 가능하지만, 유효하지 않으면 변환되지 않습니다. 언리얼에서는 Pin()이 이 기능을 하고 있습니다. 


4. 람다 함수란 무엇인가요 -> 람다 표현식에 대한 이해

람다는 함수 객체를 간단하게 정의할수 있도록 해주는 C++11에 도입된 기능입니다. 

캡쳐[] 를 통해서 람다 함수가 외부스코프의 변수를 캡쳐하는 방식으로 지정할 수 있습니다. 

따로 반환타입을 지정하지 않을경우에는 컴파일러가 직접 추론하며, 이때문에 auto를 통해서 람다 함수를 설정하면 쉽게 사용할 수 있습니다. 

[] (int x, int y) {cout << x + y;}(2,3) ;

//결과값
// 5

 

 

5. decltype이 무엇인가요 -> 새로운 C++ 문법을 알고 있는가

주어진 표현식의 타입을 추론하는데 사용되는 기능입니다. 

#include <iostream>
#include <vector>

int main() {
    int a = 42;
    decltype(a) b = a * 2; // b는 int 타입이 됩니다.

    std::vector<int> vec = {1, 2, 3};
    decltype(vec.begin()) it = vec.begin(); // it는 std::vector<int>::iterator 타입이 됩니다.

    std::cout << "a: " << a << ", b: " << b << std::endl;

    return 0;
}

 

또한 함수 반환 타입도 추론할 수 있어서, 특정 함수를 대입해도 해당 함수의 타입을 반환합니다. 

 

 

6. constexpr이 무엇인가요 -> 새로운 C++ 문법을 알고 있는가

-> 컴파일 시간에 계산되는 상수 표현식을 정의하는 기능입니다. 런타임에 실행되는 상수 표현식이 있다면 미리 constexpr을 통해서 컴파일 시간에 계산하고, 이 값을 런타임에 적용할 수 있습니다. 이를 통해 코드 최적화가 가능하며, 상수 값의 사용을 더 엄격하게 관리할 수 있습니다.