본문 바로가기
C++

[C++ 프로그래밍] 10주차 const동적 메모리 할당(new, delete)

by heeaeeeee 2023. 11. 9.

1. 고양이 클래스, 출력결과

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>

using std::cout;

class Cat {
private: // 생략 가능
	int age;           // 고양이의 나이
	char name[20];     // 고양이의 이름

public:
	// Cat 클래스의 생성자
	Cat(int age, const char* n) {
		this->age = age;     // 'this' 키워드를 사용하여 객체의 나이를 초기화
		strcpy(name, n);     // 객체의 이름을 초기화
		cout << name << " 고양이 객체가 만들어졌어요.\n";
	}

	// Cat 클래스의 소멸자
	~Cat() { cout << name << " 객체 바이\n"; };

	// 나이를 반환하는 함수
	int getAge();

	// 이름을 반환하는 함수
	const char* getName();

	// 나이를 설정하는 함수
	void setAge(int age);

	// 이름을 설정하는 함수
	void setName(const char* pName);

	// 고양이 울음소리를 출력하는 함수
	void meow();
};

// getAge 함수의 구현
int Cat::getAge() {
	return age;
}

// setAge 함수의 구현
void Cat::setAge(int age) {
	this->age = age; // 'this' 키워드를 사용하여 객체의 나이를 설정
}

// setName 함수의 구현
void Cat::setName(const char* pName) {
	strcpy(name, pName); // 객체의 이름을 설정
}

// getName 함수의 구현
const char* Cat::getName() {
	return name;
}

// meow 함수의 구현
void Cat::meow() {
	cout << name << " 고양이가 울어요\n";
}

int main() {
	// Cat 객체 생성
	Cat nabi(1, "나비"), yaong(1, "야옹"), * pNabi;

	cout << nabi.getName() << " 출생 나이는 " << nabi.getAge() << "살이다.\n";
	cout << yaong.getName() << " 출생 나이는 " << yaong.getAge() << "살이다.\n";

	pNabi = &nabi; // 포인터 pNabi에 nabi의 주소를 저장
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";

	nabi.setName("Nabi"); // nabi의 이름을 "Nabi"로 변경
	nabi.setAge(3);       // nabi의 나이를 3으로 변경
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";

	yaong.meow(); // yaong의 울음소리 출력
	nabi.meow();  // nabi의 울음소리 출력

	return 0;
}

2. 1번 소스 const char* > std::string 변경

//수정1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using std::cout;
class Cat {
private: //생략가능
	int age;
	std::string name; //A
public:
	Cat(int age, std::string n) {
		this->age = age;
	    name=n; //A
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; };
	int getAge();
	std::string getName();
	void setAge(int age);
	void setName(std::string pName);
	void meow();
};
int Cat::getAge() {
	return age;
}
void Cat::setAge(int age) {
	this->age = age; //멤버 변수 age(7줄)
}
void Cat::setName(std::string pName) {
	name=pName; //A
}
std::string Cat::getName() {
	return name;
}
void Cat::meow() {
	cout << name << "고양이가 울어요\n";
}
int main() {
	Cat nabi(1, "나비"), yaong(1, "야옹"), * pNabi;
	cout << nabi.getName() << " 출생 나이는 " << nabi.getAge() << "살이다.\n";
	cout << yaong.getName() << " 출생 나이는 " << yaong.getAge() << "살이다.\n";
	pNabi = &nabi;
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";
	nabi.setName("Nabi");
	nabi.setAge(3);
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
	yaong.meow();
	nabi.meow();
	return 0;
}

//수정2
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using std::cout;
class Cat {
private: //생략가능
	int age;
	std::string name;
	// std::string name; //A
public:
	Cat(int age, std::string name) {
		this->age = age;
	    this->name=name; //A
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; };
	int getAge();
	std::string getName();
	void setAge(int age);
	void setName(std::string pName);
	void meow();
};
int Cat::getAge() {
	return age;
}
void Cat::setAge(int age) {
	this->age = age; //멤버 변수 age(7줄)
}
void Cat::setName(std::string name) {
	this->name=name; //A
}
std::string Cat::getName() {
	return name;
}
void Cat::meow() {
	cout << name << "고양이가 울어요\n";
}
int main() {
	Cat nabi(1, "나비"), yaong(1, "야옹"), * pNabi;
	cout << nabi.getName() << " 출생 나이는 " << nabi.getAge() << "살이다.\n";
	cout << yaong.getName() << " 출생 나이는 " << yaong.getAge() << "살이다.\n";
	pNabi = &nabi;
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";
	nabi.setName("Nabi");
	nabi.setAge(3);
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
	yaong.meow();
	nabi.meow();
	return 0;
}

3. self와 this 키워드에 대해 예를 들어 설명해줘

//Python
class Person:
    def __init__(self, name):
        self.name = name   # 여기서 'self'는 객체 자신을 가리킵니다.

    def sayHello(self):
        print(f"안녕하세요, 제 이름은 {self.name}입니다.")

//c++
class Person {
private:
    std::string name;

public:
    Person(std::string name) {
        this->name = name;  // 여기서 'this'는 객체 자신을 가리킵니다.
    }

    void sayHello() {
        std::cout << "안녕하세요, 제 이름은 " << this->name << "입니다.
";
    }
};

4. const 변수

5. const 변수 예제

#define IN 1 // 컴파일 전에 IN을 찾아서 1로 바꿈
#include <iostream>
int main()
{
	const int x = 2; // 변수 x는 항상 1, 변경 불가, 초기값 지정해야
	int const y = 3; // 비추, const는 자료형 앞에 씀
	const int z{ 4 }; // Uniform initialization, C++11, z{}
	constexpr int a = 5; //C++11부터 가능, compile-time constant
	//x = 2; //변경 불가
	std::cout << IN << x << y << z << a;
	return 0;
}

6. 함수에 사용하는 const

7. const 멤버

8. const형 멤버함수 예제1 오류 수정

//수정 전
#include <iostream>
class Dog {
	int age; //private 생략함
public:
	int getAge() const;
	void setAge(int a) { age = a; }
	void view() { std::cout << "나는 view"; }
};
int Dog::getAge() const
{
	view(); // 오류 ①
	return (++age); // 오류 ②
}
int main()
{
	Dog happy;
	happy.setAge(5);
	std::cout << happy.getAge();
	return 0;
}

//수정 후
#include <iostream>
class Dog {
	int age; //private 생략함
public:
	int getAge() const;
	void setAge(int a) { age = a; }
	void view() const { 
		std::cout << "나는 view"; 
	}
};
int Dog::getAge() const
{
	view(); //오류 ① 
    // const 멤버함수는 const 함수만 호출할 수 있고, 일반 함수를 호출할 수 없다. 여기서 view함수가 const 함수라면 가능하다. 
	return age; //오류 ② 
    // const 멤버함수에서는 멤버변수 age를 변경(++age)할 수 없다.
}
int main()
{
	Dog happy;
	happy.setAge(5);
	std::cout << happy.getAge();
	return 0;
}

set으로 시작하는 함수에는 const 붙일 수 없음

9. const 객체 예제2 오류 수정

//수정 전
#include <iostream>
class Dog {
	int age;
public:
	Dog(int a) { age = a; }
	int getAge() const;
	void setAge(int a) { age = a; }
	void view() const {
		std::cout << "나는 view\n";
	}
};
int Dog::getAge() const
{
	view();
	return (age);
}
int main()
{
	const Dog happy(5); //const 객체
	happy.setAge(7); // 오류
	std::cout << happy.getAge();
	return 0;
}

//수정 후
#include <iostream>
class Dog {
	int age;
public:
	Dog(int a) { age = a; }
	int getAge() const;
    //해당 클래스의 어떠한 멤버변수도 바꾸지 않는 멤버함수(get으로 시작하는함수)는 const형으로 선언하는 것이 좋다.
	void setAge(int a) { age = a; }
	void view() const {
		std::cout << "나는 view\n";
	}
};
int Dog::getAge() const 
{
	view();
	return (age);
}
int main()
{
	Dog happy(5); //const 객체 happy에는 const로 지정된 멤버함수만 호출할 수 있다.
	//happy.setAge(7); 생략
	std::cout << happy.getAge();
	return 0;
}

10. 정적 vs. 동적 메모리 할당

#include <iostream>
int main()
{
	int array[1000000]; //4MB
	//지역변수는 스택에 저장하는데기본 스택 크기를 넘어서 오류
	std::cout << "aaaa";
	return 0;
}//VS에서 실행될까?
//다른 컴파일러에서도 더 크게 잡으면
//exited, segmentation fault

11. 하나의 정수에 대한 메모리 할당과 해제 : 정적 vs. 동적

#include <iostream>
int main()
{
	int* pi = new int; // 동적 메모리 할당
	int x;
	if (!pi) { // pi==0, 널 포인터인지 확인
		std::cout << "메모리할당이 되지 않았습니다.";
		return 1; //비정상 종료시 리턴값
	}
	*pi = 100; //주소의 값으로 100을 할당
	x = 10;
	std::cout << "동적메모리=" << *pi << ", x=" << x;
	delete pi; // 메모리 해제
	return 0; // 정상 종료시 리턴값
}

new를 쓰면 delete 해야한다. 하지 않으면 프로그램이 끝나도 메모리 낭비 > 다른 프로그램이 사용 못함

12. 동적 메모리를 사용하는 이유

13. 동적 메모리의 할당과 해제: new와 delete

14. Variable-length Array : 실행 가능?

#include <iostream>
int main()
{
	int i;
	std::cout << "몇 개==";
	std::cin >> i;
	int num[i]; //원래 C표준에서 배열의 크기는 컴파일시 결정되어야 함
	return 0;
}

C++ 표준에서는 실행 시점에 크기가 결정되는 Variable-Length Array (VLA)를 지원하지 않습니다. 일부 컴파일러에서는 확장 기능으로 VLA를 지원하지만, 이는 표준이 아니며 이식성이 떨어집니다. 따라서 C++에서는 실행 시점에 크기가 결정되는 배열이 필요할 때 std::vector를 사용하는 것이 권장됩니다.

15. 동적메모리 할당(필요한 만큼의 메모리만 실행시 할당)

#include <iostream>   // 입출력을 위한 라이브러리를 포함
#include <stdlib.h>   // exit 함수를 사용하기 위한 라이브러리를 포함

int main()
{
    int i, n;               // 사용자로부터 입력받을 숫자의 개수(i)와 반복문에서 사용할 변수(n)를 선언
    int* num;               // 동적으로 할당할 정수형 배열을 가리킬 포인터를 선언

    std::cout << "몇 개의 숫자를 입력하시겠습니까==";  // 사용자에게 숫자의 개수를 입력받기 위한 메시지 출력
    std::cin >> i;          // 사용자로부터 숫자의 개수를 입력받음

    num = new int[i];       // 사용자가 입력한 수(i)만큼 정수형 배열을 동적으로 할당

    if (num == NULL) exit(1); // 동적 할당이 제대로 이루어지지 않았을 경우 프로그램 종료

    for (n = 0; n < i; n++)   // 사용자로부터 숫자를 입력받는 반복문
    {
        std::cout << "숫자를 입력하십시오 : ";  // 사용자에게 숫자를 입력하라는 메시지 출력
        std::cin >> num[n];                    // 사용자로부터 숫자를 입력받아 동적으로 할당한 배열에 저장
    }

    std::cout << "당신이 입력한 숫자는: ";    // 사용자가 입력한 숫자를 출력하는 메시지 출력

    for (n = 0; n < i; n++)   // 사용자가 입력한 숫자를 출력하는 반복문
        std::cout << num[n] << ", ";  // 사용자가 입력한 숫자를 출력

    delete[] num; // 동적으로 할당한 메모리를 해제. []를 생략하면 배열의 모든 요소가 제대로 해제되지 않을 수 있음

    return 0;     // 프로그램이 성공적으로 종료되었음을 운영체제에 알림
}

16. 객체 동적할당

#include <iostream>
class Dog {
private:
	int age;
public:
	int getAge();
	void setAge(int a);
};
int Dog::getAge()
{
	return age;
}
void Dog::setAge(int a)
{
	age = a;
}
int main()
{
	Dog* dp;
	dp = new Dog; // Dog *dp=new Dog
	if (!dp) {
		std::cout << "메모리할당 불가!";
		return 1;
	}
	dp->setAge(5);
	std::cout << "메모리에 할당된 값은 "
		<< dp->getAge() << "입니다.";
	delete dp;
	return 0;
}

17. 배열객체 동적 할당

#include <iostream>
class Dog {
private:
	int age;
public:
	int getAge();
	void setAge(int a);
};
int Dog::getAge()
{
	return age;
}
void Dog::setAge(int a)
{
	age = a;
}
int main()
{
	Dog* dp;
	dp = new Dog[10]; // 객체배열 할당
	// Dog *dp=new Dog[10];
	if (!dp) {
		std::cout << "메모리할당이 되지 않았습니다.";
		return 1;
	}
	for (int i = 0; i < 10; i++) // C++에서는 가능
		dp[i].setAge(i);
	for (int i = 0; i < 10; i++)
		std::cout << i << "번째 객체의 나이는 " <<
		dp[i].getAge() << " 입니다. " << std::endl;
	delete[]dp;
	return 0;
}

18. 고양이 클래스2

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using std::cout;
class Cat {
private: //생략가능
	int age;
	std::string name;
public:
	Cat(int age, std::string n) {
		this->age = age;
		name = n;
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; };
	int getAge() const;
	std::string getName() const;
	void setAge(int age);
	void setName(std::string pName);
	void meow() const;
};
int Cat::getAge() const {
	return age;
}
void Cat::setAge(int age) {
	this->age = age;
}
void Cat::setName(std::string pName) {
	name = pName;
}
std::string Cat::getName() const {
	return name;
}
void Cat::meow() const {
	cout << name << "고양이가 울어요\n";
}
int main() {
	Cat nabi(1, "나비"), yaong(1, "야옹"), * pNabi;
	cout << nabi.getName() << " 출생 나이는 " << nabi.getAge() << "살이다.\n";
	cout << yaong.getName() << " 출생 나이는 " << yaong.getAge() << "살이다.\n";
	pNabi = &nabi;
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";
	nabi.setName("Nabi");
	nabi.setAge(3);
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
	yaong.meow();
	nabi.meow();
	return 0;
}

 

 

C++ 강의 자료 참고했습니다.