StatInfo)를 함수에서 만들고 전달하는 3가지 방식StatInfo CreatePlayer() {
StatInfo info = {100, 10, 2};
return info; // 값으로 반환
}
StatInfo player = CreatePlayer();
info는 함수의 지역 변수라서 함수가 끝나면 스택 프레임과 함께 사라집니다.보너스 감각: “복사 비용”이 걱정될 수 있지만, 컴파일러 최적화(RVO/NRVO 등)로 비용이 줄어드는 경우가 많습니다.
초반 학습 단계에서는 안전한 코드가 우선입니다.
void CreateMonster(StatInfo* info) {
if (info == nullptr)
return;
info->hp = 40;
info->attack = 8;
info->defence = 1;
}
StatInfo monster;
CreateMonster(&monster);
nullptr로 “대상이 없다”를 표현 가능void CreateMonsterRef(StatInfo& info) {
info.hp = 40;
info.attack = 8;
info.defence = 1;
}
void Battle(StatInfo* player, StatInfo* monster) {
if (player == nullptr || monster == nullptr)
return;
while (true) {
int damage = player->attack - monster->defence;
if (damage < 0) damage = 0;
monster->hp -= damage;
if (monster->hp <= 0) return;
damage = monster->attack - player->defence;
if (damage < 0) damage = 0;
player->hp -= damage;
if (player->hp <= 0) return;
}
}
0으로 고정(clamp)하는 처리도 자주 추가합니다.핵심: 지역 변수의 주소를 반환하면, 함수가 끝나는 순간 그 주소는 더 이상 “내 데이터”가 아닙니다.
StatInfo* CreatePlayer2() {
StatInfo info = {100, 10, 2};
return &info; // ❌ 함수 종료 시 info는 스택에서 소멸
}
StatInfo* player = CreatePlayer2();
std::cout << player->hp << '\n'; // 쓰레기값 또는 크래시
info는 CreatePlayer2의 스택 프레임 내부에 있었기 때문에, 함수가 끝나면 그 프레임이 반납됩니다.&info로 얻은 주소는 “그냥 어떤 스택 자리”를 가리키는 값이 되어버리고,개념 그림:
CreatePlayer2() 프레임 안의 info 주소를 반환
┌────────── CreatePlayer2 프레임 ──────────┐
│ info {hp=100, attack=10, defence=2} │ ← &info
└─────────────────────────────────────────┘
함수 종료 → 프레임 반납 → 이 자리는 곧 덮어써질 수 있음
StatInfo CreatePlayer() 처럼 반환void CreatePlayer(StatInfo& out) 형태new로 만들고 수동 해제(delete)가 필요return &info;가 위험한 이유를 “스택 프레임” 관점으로 설명해보자.포인터 인자와 참조 인자는 언제 선택하는 게 더 좋을까?