인프런 커뮤니티 질문&답변

Jay Jae님의 프로필 이미지
Jay Jae

작성한 질문수

이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해

10강에서 reinterpret_cast 질문있습니다

해결된 질문

작성

·

58

0

인터넷에서 찾아보니

 

casting 중에서도 가장 강한 cast이며, 주로 패킷 통신할 때 자료를 포인터로 받아오는 경우에 사용하며 그 외엔 잘 사용하지 않는 형변환이다. 포인터끼리, 그리고 포인터와 수치형 간의 변환

 

이라고 하는데 혹시 ABCharacterStat.h에서 operator+ 구현할 때, reinterpret_cast를 사용하는게 더 좋은 이유가 있을까요? 캐스팅 종류가 많아서 너무 헷갈리네요... 만약에 굳이 reinterpret_cast를 쓰지 않아도 된다면 일반 casting으로도 대체가 가능한지요?

 

아 그리고 추가로, part2를 다 들으면서 계속 궁금했었던건데 왠만한 모든 변수 선언 시에는 대부분 const를 붙여서 선언하시던데 const가 값을 바꾸지 않는 상수화이지 않나요??

제가 유니티만 하다가 언리얼로 최근에 바꿨는데 그래서 그런가 제일 적응안되는부분이 모든 변수를 포인터로 쓰는 것과 항상 변수에 const를 붙이는 부분이더라구요. 변수를 포인터로 선언하는 이유는 인터넷 검색으로 이해가 되었는데, const를 거의 항상 사용하는 이유는 아직 잘 모르겠습니다... 변수를 상수화 시키는 것이 어떤 의미가 있는걸까요?? 변수의 값은 보통 게임이 진행되면서 계속 바뀌어야 하지 않나요??

답변 2

0

이득우님의 프로필 이미지
이득우
지식공유자

안녕하세요.

C#에서 C++로 넘어올 때 깨우쳐야 할 개념 중 하나는 컴파일러의 역할이라고 생각합니다. 

C++컴파일러는 발전해오면서 단순히 구문을 기계어로 바꿔주는 역할에서 벗어나 런타임에서 발생할 문제를 사전에 예측하고 해결책을 제시하도록 많은 부분이 개선되었습니다.

두 가지 중요한 개념이 레퍼런스와 const인데요, 프로그래머로 하여금 함수를 타고 이동하는 값에 대한 복사처리 여부와 읽기 전용인지(기존 값을 유지시키는지)에 대한 부분을 고민하도록 권장하고 있습니다.

그렇기에 어떤 변수를 선언할 때 상수인지 변수인지에 대한 고민이 필요하고, 함수를 구성할 때도 함수의 성격과 인자를 다루는 방식을 고민해야합니다. 실제로 이런 부분을 잘 지키면 메모리를 효과적으로 이용하면서 런타임에서 오작동할 수 있는 많은 부분을 미연에 방지할 수 있습니다.  

캐스팅도 이러한 관점에서 생각해주면 되겠습니다. 사실 캐스팅자체는 데이터를 변경하거나 작업을 수행하는게 아니고 컴파일러에게 데이터 구조를 설명하는 것에 불과합니다. 일반적인 캐스팅은 현재 만들어진 객체지향 구조에 맞게 형변환하고 있다고 설명하는 작업이라고 보면 됩니다.

하지만 지금 예제의 경우 구조체 데이터를 아무 연고도 없는 float 배열로 변경하라고 제시하고 있습니다. 이는 컴파일러에게 불안하겠지만 나를 믿어봐라고 설명하는 작업으로 이해하면 되고, 이의 지시자가 reinterpret_cast인 것입니다.

다만 이후에 발생하는 실수는 모두 개발자가 스스로 책임져야죠. 예를 들어 구조체 멤버변수를 모두 float으로 선언해야함에도 실수로 멤버변수 하나를 int32로 선언했다면 나중에 이상한 값이 읽혀 프로그램에 오류가 날텐데. 이는 컴파일러가 감지할 수 없고 오롯이 개발자가 책임져야 하는 것이다보니 일반적으로는 그리 권장하지는 않는 캐스팅입니다. 

Jay Jae님의 프로필 이미지
Jay Jae
질문자

상세한 설명 너무나도 감사합니다!! 유니티랑 언리얼이 둘 다 게임 만드는 엔진이니까 얼추 비슷할줄 알고 가벼운 마음으로 언리얼에 입문했는데 생각보다 엄청나게 높은 벽이 존재하네요... C++을 배우고 나서 C# 쓸땐 몰랐는데, C#을 쓰다가 C++로 돌아오니 불편한 점이 한두가지가 아닌 것 같습니다... 위에 강사님께서 말씀해주신 const와 레퍼런스에 대한 내용은 저장해놓고 저 내용이 머리속에서 익숙하게 그려질때까지 두고두고 봐야겠어요 정말 감사합니다

0

안녕하세요, 인프런 AI 인턴입니다. Jay Jae님.

reinterpret_cast에 대한 질문

reinterpret_cast는 특히 포인터 간 형변환에서 많이 사용되며, 꽤 강력하고 위험할 수 있는 형태의 형변환입니다. 주로 메모리의 내용을 그대로 다른 타입으로 변환해야 하는 경우에 사용됩니다. 예를 들어, FABCharacterStatoperator+ 구현 시 자료를 float 타입으로 해석하여 각 멤버의 값을 더하는 경우에 reinterpret_cast가 사용되었을 것입니다.

하지만 reinterpret_cast는 반드시 필요한 상황이 아니라면 사용을 지양하는 것이 좋습니다. 메모리 손상이 일어나기 쉽고, 코드의 가독성 및 유지보수성을 떨어뜨리기 때문입니다.

관련 질문

16:29 uint8*을 FABCharacterStat*로 다시 형변환 하는이유

정리하면, reinterpret_cast는 포인터와 다른 타입 간 변환에 사용되며, 사용 이유는 포인터 타입의 메모리 주소를 다른 타입으로 변환하여 동일한 메모리 위치에서 다른 타입의 데이터를 접근하기 위해서 입니다. 성능보다는 데이터 접근 방식에 관한 이유가 큽니다. 따라서, 만약 단순한 형변환으로 되는 경우라면 다른 캐스팅을 고려해볼 수도 있습니다.

const 사용 이유

C++에서 const 키워드는 해당 변수가 변경되지 않음을 보장합니다. 이는 여러 가지 이유로 중요하며, 주로 코드의 안정성과 가독성을 높이기 위해 사용됩니다:

  1. 데이터 무결성 보장: 특정 변수의 값이 변경되지 않음을 보장함으로써, 함수나 객체가 예기치 않게 값을 변동시키지 않도록 방지합니다.

  2. 코드 가독성 증가: 어떤 값이 변화하지 않는다는 사실을 코드 상에서 명시적으로 표현함으로써, 다른 개발자들이 코드를 읽을 때 쉽게 이해할 수 있습니다.

  3. 최적화 가능성: 컴파일러에게 변수의 값을 변경하지 않는다는 정보를 제공하여, 최적화를 더 잘 수행할 수 있게 합니다.

관련 질문

StaticClass 나 에셋 레퍼런스 경로로 클래스를 사용한다는 의미

결론적으로, 언리얼 엔진에서는 성능 최적화와 코드 안정성을 위해 const를 최대한 활용합니다. 유니티와는 다른 언어적 특성과 철학을 가지고 있으므로, 언리얼 엔진의 C++ 프로그래밍에 적응하는 과정으로 이해하시면 좋을 것 같습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Jay Jae님의 프로필 이미지
Jay Jae

작성한 질문수

질문하기