본문 바로가기
ProgramingLagnuage/C++

[C/C++] 동적 메모리 할당 방식, 변수 취급 방식 차이

by TSpoons 2024. 12. 31.

메모리

 
프로그램 실행 시 자유롭게 할당하고 해제할 수 있는 힙(heap) 메모리 공간이 생김
 
-> 스택(stack)과 다르게 메모리 누수를 프로그래머가 담당해야 함.
 
 

C언어의 특징:

  1. 메모리 관리 방식
    • 정적/전역 변수: 컴파일 시점에 주소값이 확정
    • 동적 할당 변수: malloc/free를 통해 런타임에 메모리를 관리
  2. 프로그래머 제어 중시
    • malloc은 void*를 반환하여 프로그래머가 명시적 타입 변환
    • 메모리 초기화를 프로그래머가 직접 

C++의 특징:

  1. 메모리 관리 방식
    • 정적/전역 변수: C와 동일하게 컴파일 시점에 주소값이 확정
    • 동적 할당 변수: new/delete를 통해 런타임에 메모리를 관리
  2. 타입 안전성 중시
    • new는 지정된 타입의 포인터를 직접 반환
    • 생성자를 통해 자동으로 초기화
    • 실패 시 예외 처리를 제공
  3. 객체 지향적 접근
    • RAII(Resource Acquisition Is Initialization) 패턴 지원
    • 스마트 포인터를 통한 자동 메모리 관리 가능
    • 생성자/소멸자를 통한 자원 관리

C는 프로그래머에게 더 많은 제어를 제공하는 반면,
C++은 안전성과 편의성을 더 강조합니다.
 
 
 
 

 /* new, delete 사용*/
 #include <iostream>
 
 int main() {
 	int* p = new int;
 	*p = 10;
    
 	std::cout << *p << std::endl;
    
 	delete p;
 	return 0;
 }

 
 
지역 변수를 강제로 delete로 해제하려고 하면 다음과 같은 Heap이 아닌 공간을 해제하려고 한다.

 
 
 
 
 

#include <iostream>

int main()
{
	int arr_size;
	std::cout << "배열의 크기를 입력하세요: ";
	std::cin >> arr_size;

	int* arr = new int[arr_size];
	for (int i = 0; i < arr_size; i++)
	{
		arr[i] = i;
	}


	for (int i = 0; i < arr_size; i++)
	{
		std::cout << arr[i] << std::endl;
	}

	delete[] arr;
	return 0;

 

 
 
 
 
 
 
C/ C++ 비교
 
인적사항을 적는 프로그램이 있다고 하자.
 

#include <iostream>
typedef struct Person {
	char name[30]; // 이름
	int age;// 나이

	float height; // 키
	double weight; // 몸무게

}Person;

void create_person(Person* person) {
    std::cout << "학생의 이름? ";
    std::cin >> person->name;
    std::cout << "학생의 나이? ";
    std::cin >> person->age;
    std::cout << "학생의 키(cm)? ";
    std::cin >> person->height;
    std::cout << "학생의 몸무게(kg)? ";
    std::cin >> person->weight;
}

// 사람 정보 출력 함수
void show_info(Person* person) {
    std::cout << person->name << "의 정보" << std::endl;
    std::cout << "나이 : " << person->age << "세" << std::endl;
    std::cout << "키 : " << person->height << "cm" << std::endl;
    std::cout << "몸무게 : " << person->weight << "kg" << std::endl;
}

// 사용 예시:
int main() {
	Person* list[10];
	int person_count = 0;

    while(1){
        std::cout << "1. 인적사항 추가하기" << std::endl;
        std::cout << "2. 정보보기 " << std::endl;
        std::cout << "3. 종료" << std::endl;

        
        int input;
        std::cin >> input;

        switch (input) {
            case 1:
			    list[person_count] = new Person;
			    create_person(list[person_count]);
			    person_count++;
                break;
            case 2:
                std::cout << "현재 저장된 사람 목록:" << std::endl;
                for (int i = 0; i < person_count; i++) {
                    std::cout << i + 1 << ". " << list[i]->name << std::endl;
                }
                int index;
                std::cout << "번호를 선택하세요 (1-" << person_count << "): ";
                std::cin >> index;

                if (index < 1 || index > person_count) {
                    std::cout << "잘못된 번호입니다!" << std::endl;
                    break;
                }

                show_info(list[index - 1]);
                break;
            case 3:
				std::cout << "프로그램을 종료합니다." << std::endl;
				return 0;
			default:
				std::cout << "잘못된 입력입니다." << std::endl;
				break;
        }
    
    }

	for (int i = 0; i < person_count; i++) {
		delete list[i];
	}
    return 0;
}

 
 
기존에 만들어진 프로그램은 사람으로 통틀어서 적었는데
이번에는 교사, 학생, 학부모까지 적어보자.
 

 
 
 
1. 코드 중복

// 1. 코드 중복 문제
void show_info_person(Person* p) {
    std::cout << p->name << "의 정보" << std::endl;
    std::cout << "나이: " << p->age << std::endl;
    std::cout << "키: " << p->height << std::endl;
    std::cout << "몸무게: " << p->weight << std::endl;
}

void show_info_student(Student* s) {  // Person 정보 출력이 중복됨
    std::cout << s->person.name << "의 정보" << std::endl;
    std::cout << "나이: " << s->person.age << std::endl;
    std::cout << "키: " << s->person.height << std::endl;
    std::cout << "몸무게: " << s->person.weight << std::endl;
    std::cout << "학년: " << s->grade << std::endl;
    // ...
}

 
 
2. 배열 관리

int main() {
    // 각각 다른 타입의 배열을 따로 관리해야 함
    Person* person_list[10];
    Student* student_list[10];
    Teacher* teacher_list[10];
    Parent* parent_list[10];
    
    // 전체 구성원을 한번에 처리하고 싶어도 할 수 없음
    // 각각 따로 처리해야 함
    show_info_person(person_list[0]);
    show_info_student(student_list[0]);
    show_info_teacher(teacher_list[0]);
    
    return 0;
}

 
 
 
 
 
 
 
 
 
 

class Person {
protected:  // 상속받은 클래스에서 접근 가능
    string name;
    int age;
    float height;
    double weight;
    
public:
    virtual void show_info() {  // 한 번만 구현
        cout << name << "의 정보" << endl;
        cout << "나이: " << age << endl;
        cout << "키: " << height << endl;
        cout << "몸무게: " << weight << endl;
    }
};

class Student : public Person {  // Person의 모든 기능을 상속
    int grade;
    int class_num;
    int student_num;
    
public:
    void show_info() override {  // Person의 정보 출력을 재사용
        Person::show_info();     // 기존 Person의 show_info 호출
        cout << "학년: " << grade << endl;
        // ... 추가 정보만 출력
    }
};

class Teacher : public Person {  // Person의 모든 기능을 상속
    string subject;
    int career;
    
public:
    void show_info() override {
        Person::show_info();    // 중복 코드 없음!
        cout << "과목: " << subject << endl;
        // ... 추가 정보만 출력
    }
};

int main() {
    // 하나의 배열로 모든 타입 관리 가능!
    Person* people[10];
    people[0] = new Student();
    people[1] = new Teacher();
    
    // 한 번의 반복문으로 모든 구성원 처리 가능
    for(int i = 0; i < 10; i++) {
        people[i]->show_info();  // 각 타입에 맞는 show_info가 자동으로 호출됨
    }
    
    return 0;
}

 
 
 
 

#include <iostream>
#include <string>
#include <vector>

class Person {
protected:
    std::string name;
    int age;
    float height;
    double weight;

public:
    Person(std::string n = "", int a = 0, float h = 0, double w = 0)
        : name(n), age(a), height(h), weight(w) {}
    
    virtual ~Person() {}  // 가상 소멸자

    virtual void inputInfo() {
        std::cout << "이름? ";
        std::cin >> name;
        std::cout << "나이? ";
        std::cin >> age;
        std::cout << "키(cm)? ";
        std::cin >> height;
        std::cout << "몸무게(kg)? ";
        std::cin >> weight;
    }

    virtual void showInfo() const {
        std::cout << name << "의 정보" << std::endl;
        std::cout << "나이: " << age << "세" << std::endl;
        std::cout << "키: " << height << "cm" << std::endl;
        std::cout << "몸무게: " << weight << "kg" << std::endl;
    }

    std::string getName() const { return name; }
};

class Student : public Person {
private:
    int grade;
    int class_num;
    int student_num;

public:
    void inputInfo() override {
        Person::inputInfo();
        std::cout << "학년? ";
        std::cin >> grade;
        std::cout << "반? ";
        std::cin >> class_num;
        std::cout << "번호? ";
        std::cin >> student_num;
    }

    void showInfo() const override {
        Person::showInfo();
        std::cout << "학년: " << grade << std::endl;
        std::cout << "반: " << class_num << std::endl;
        std::cout << "번호: " << student_num << std::endl;
    }
};

class Teacher : public Person {
private:
    std::string subject;
    int career;

public:
    void inputInfo() override {
        Person::inputInfo();
        std::cout << "담당 과목? ";
        std::cin >> subject;
        std::cout << "경력(년)? ";
        std::cin >> career;
    }

    void showInfo() const override {
        Person::showInfo();
        std::cout << "담당 과목: " << subject << std::endl;
        std::cout << "경력: " << career << "년" << std::endl;
    }
};

class SchoolManagement {
private:
    std::vector<Person*> people;

public:
    ~SchoolManagement() {
        for (Person* person : people) {
            delete person;
        }
    }

    void addPerson() {
        std::cout << "1. 학생 추가" << std::endl;
        std::cout << "2. 교사 추가" << std::endl;
        int choice;
        std::cin >> choice;

        Person* person = nullptr;
        switch (choice) {
            case 1:
                person = new Student();
                break;
            case 2:
                person = new Teacher();
                break;
            default:
                std::cout << "잘못된 선택입니다." << std::endl;
                return;
        }

        person->inputInfo();
        people.push_back(person);
    }

    void showPeopleList() const {
        if (people.empty()) {
            std::cout << "저장된 정보가 없습니다." << std::endl;
            return;
        }

        std::cout << "현재 저장된 사람 목록:" << std::endl;
        for (size_t i = 0; i < people.size(); i++) {
            std::cout << i + 1 << ". " << people[i]->getName() << std::endl;
        }

        std::cout << "번호를 선택하세요 (1-" << people.size() << "): ";
        size_t index;
        std::cin >> index;

        if (index < 1 || index > people.size()) {
            std::cout << "잘못된 번호입니다!" << std::endl;
            return;
        }

        people[index - 1]->showInfo();
    }
};

int main() {
    SchoolManagement school;

    while (true) {
        std::cout << "\n1. 인적사항 추가하기" << std::endl;
        std::cout << "2. 정보보기" << std::endl;
        std::cout << "3. 종료" << std::endl;
        
        int input;
        std::cin >> input;

        switch (input) {
            case 1:
                school.addPerson();
                break;
            case 2:
                school.showPeopleList();
                break;
            case 3:
                std::cout << "프로그램을 종료합니다." << std::endl;
                return 0;
            default:
                std::cout << "잘못된 입력입니다." << std::endl;
                break;
        }
    }
}

'ProgramingLagnuage > C++' 카테고리의 다른 글

[C++] 객체지향 프로그래밍  (0) 2025.01.01
[C++] 템플릿 프로그래밍(template programming)  (0) 2024.10.18
[C++] 사용자 정의 유형 - Structure  (0) 2024.09.23
[C++] C++ 소개  (0) 2024.09.22
[C++] Class 주요 개념  (0) 2024.09.22