전체 코드

using System;

namespace CSharp
{
    // 🔹 구조체 (값 타입 - 스택)
    struct Mage
    {
        public int hp;
        public int attack;
    }

    // 🔹 클래스 (참조 타입 - 힙)
    class Knight
    {
        public int hp;
        public int attack;

        // 🔹 깊은 복사 (Deep Copy) 메서드
        public Knight Clone()
        {
            Knight knight = new Knight();  // 새로운 Knight 객체를 생성 (힙 메모리에 할당)
            knight.hp = this.hp;           // 현재 Knight 객체의 hp 복사
            knight.attack = this.attack;   // 현재 Knight 객체의 attack 복사
            return knight;                 // 복사된 객체 반환
        }

        public void Move() { Console.WriteLine("Knight Move"); }
        public void Attack() { Console.WriteLine("Knight Attack"); }
    }

    class Program
    {
        // 🔹 값 타입 (스택) - 복사본을 전달
        static void KillMage(Mage mage)
        {
            mage.hp = 0;  // mage 구조체의 사본을 변경 → 원본에는 영향 없음
        }

        // 🔹 참조 타입 (힙) - 원본을 변경
        static void KillKnight(Knight knight)
        {
            knight.hp = 0;  // knight 객체의 원본을 변경 (같은 객체를 참조)
        }

        static void Main(string[] args)
        {
            // 🔹 값 타입 (Struct - Stack)
            Mage mage;
            mage.hp = 100;
            mage.attack = 50;

            Mage mage2 = mage;  // mage의 값을 mage2에 복사 (깊은 복사)
            mage2.hp = 0;       // mage2의 hp만 변경, 원본 mage는 영향 없음

            // 🔹 참조 타입 (Class - Heap)
            Knight knight = new Knight();  // 새로운 Knight 객체 생성 (힙 메모리에 할당)
            knight.hp = 100;
            knight.attack = 10;

            //KillKnight(knight);  // knight.hp = 0; 호출하면 원본 knight도 변경됨

            // 🔹 얕은 복사 vs 깊은 복사
            // Knight knight2 = knight;  // 얕은 복사 (같은 객체를 참조)
            Knight knight2 = knight.Clone();  // 깊은 복사 (새로운 객체 생성)

            knight2.hp = 0;  // knight2의 hp만 변경됨, knight는 영향 없음
        }
    }
}


1️⃣ 스택(Stack)과 힙(Heap) 비교

구분스택(Stack) 메모리힙(Heap) 메모리
메모리 위치고정된 크기의 메모리 영역동적 크기의 메모리 영역
저장 대상지역 변수, 매개변수, 값 타입(Struct)객체, 배열, 클래스 인스턴스(Reference Type)
할당 방식함수 호출 시 자동 할당new 키워드로 동적 할당
해제 방식함수가 종료되면 자동 해제C#의 가비지 컬렉터(GC)가 자동 해제
메모리 속도빠름 (자동 해제)상대적으로 느림 (GC 작동 시기까지 유지)
메모리 특징LIFO (Last In, First Out) 구조동적 크기 조절 가능

스택 → 빠른 할당/해제, 지역 변수 저장, 함수 종료 시 자동 삭제
→ 동적 할당, 참조 타입 저장, 프로그램 실행 중에도 유지 가능


2️⃣ 코드 분석 (상세 설명)

📌 1) 구조체(Struct) - 값 타입 복사 (스택)

struct Mage
{
    public int hp;     // 체력
    public int attack; // 공격력
}

구조체(Struct) → 값 타입이므로 복사 시 새로운 객체가 생성됨
스택(Stack) 메모리에 저장Mage mage2 = mage; 하면 새로운 메모리가 할당됨
Mage 구조체를 복사하면 hpattack 값이 그대로 복사되지만, 두 객체는 서로 영향을 주지 않음

Mage mage;
mage.hp = 100;
mage.attack = 50;

Mage mage2 = mage;  // 값 복사
mage2.hp = 0;       // mage2의 hp만 변경됨, 원본 mage는 영향 없음

📌 2) 클래스(Class) - 참조 타입 복사 (힙)

class Knight
{
    public int hp;
    public int attack;
}

클래스(Class) → 참조 타입이므로 복사 시 같은 객체를 가리킴
힙(Heap) 메모리에 저장Knight knight = new Knight(); 해야 객체가 생성됨
Knight knight2 = knight; 하면 knight2와 knight는 같은 객체를 공유

Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;

Knight knight2 = knight;  // 얕은 복사
knight2.hp = 0;           // knight2의 hp를 변경하면 knight도 변경됨

➡ knight2는 knight와 동일한 객체를 참조하기 때문에 하나를 변경하면 나머지도 변경됨 (얕은 복사).


📌 3) 깊은 복사(Deep Copy)

    public Knight Clone()
    {
        Knight knight = new Knight();
        knight.hp = this.hp;
        knight.attack = this.attack;
        return knight;
    }

Clone() 메서드를 사용하여 새로운 객체를 생성하고 모든 속성을 복사
Knight knight2 = knight.Clone(); 하면 knight2는 knight와 독립적인 객체

Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;

Knight knight2 = knight.Clone();  // 깊은 복사
knight2.hp = 0;                   // knight2의 hp만 변경됨, knight는 영향 없음

📌 4) 매개변수 전달 - 값 타입 vs 참조 타입

    static void KillMage(Mage mage)
    {
        mage.hp = 0;  // mage 구조체를 복사하여 사용 (원본 영향 없음)
    }

    static void KillKnight(Knight knight)
    {
        knight.hp = 0;  // knight 객체의 참조를 전달받아 원본이 변경됨
    }

구조체(값 타입)KillMage(mage);를 호출해도 원본 mage는 변경되지 않음
클래스(참조 타입)KillKnight(knight);를 호출하면 원본 knighthp가 0으로 변경됨

Mage mage;
mage.hp = 100;

KillMage(mage);  // 호출 후에도 mage.hp == 100 (영향 없음)

Knight knight = new Knight();
knight.hp = 100;

KillKnight(knight);  // 호출 후 knight.hp == 0 (원본 변경됨)

profile
李家네_공부방

0개의 댓글