C++ Const, 동적 메모리 할당

2023. 11. 9. 16:18C++

지난시간 배웠던 Class 예시 소스

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using std::cout;
class Cat {
private: //생략가능
	int age;
	char name[20];
	// const char* name; //A
public:
	Cat(int age, const char* n) {
		this->age = age;
		strcpy(name, n); // name=n; //A
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; };
	int getAge();
	const char* getName();
	void setAge(int age);
	void setName(const char* pName);
	void meow();
};
int Cat::getAge() {
	return age;
}
void Cat::setAge(int age) {
	this->age = age;  //this->age는 멤버변수 age를 가르킨다
}
void Cat::setName(const char* pName) {
	strcpy(name, pName);
	//strcpy(대상주소, 원본주소);
	//strcpy_s(대상주소, 대상의길이, 원본주소);
	//name=pName; //A
}
const char* 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;
}

실행 결과

나비고양이 객체가 만들어졌어요.
야옹고양이 객체가 만들어졌어요.
나비 출생 나이는 1살이다.
야옹 출생 나이는 1살이다.
나비 출생 나이는 1살이다.
Nabi 나이는 3살이다.
야옹고양이가 울어요
Nabi고양이가 울어요
야옹객체 바이
Nabi객체 바이

배열을 string으로 변경

#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 n) {// 생성자
		this->age = age;
		name = n; //strcpy()는 배열을 복사할때 쓰는 함수 string형 변수는 그냥 대입
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; }; //객체가 소멸할때 name+객체 바이 라고 출력한다
	int getAge();
	std::string getName();
	void setAge(int age);
	void setName(std::string pName);
	void meow();
};
int Cat::getAge() {//멤버변수 age값을 리턴
	return age;
}
void Cat::setAge(int age) {
	this->age = age;  //this->age는 멤버변수 age를 가르킨다
}
void Cat::setName(std::string pName) {
	name = pName;
	
}
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;//포인터 객체 pNabi의 주소에 nabi의 값을 대입한다 주소로 접근
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";//pNabi를 출력했지만 nabi의 값이 들어가있기 때문에 nabi값 출력
	nabi.setName("Nabi");
	nabi.setAge(3);
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
	yaong.meow();
	nabi.meow();
	return 0;
}

this->를 사용하여 깔끔하게 바꾸기

 

#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; //strcpy()는 배열을 복사할때 쓰는 함수 string형 변수는 그냥 대입
		cout << name << "고양이 객체가 만들어졌어요.\n";
	}
	~Cat() { cout << name << "객체 바이\n"; }; //객체가 소멸할때 name+객체 바이 라고 출력한다
	int getAge();
	std::string getName();
	void setAge(int age);
	void setName(std::string name);
	void meow();
};
int Cat::getAge() {//멤버변수 age값을 리턴
	return age;
}
void Cat::setAge(int age) {
	this->age = age;  //this->age는 멤버변수 age를 가르킨다
}
void Cat::setName(std::string name) {
	this->name = name;
	
}
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;//포인터 객체 pNabi의 주소에 nabi의 값을 대입한다 주소로 접근
	cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";//pNabi를 출력했지만 nabi의 값이 들어가있기 때문에 nabi값 출력
	nabi.setName("Nabi");
	nabi.setAge(3);
	cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
	yaong.meow();
	nabi.meow();
	return 0;
}

Const 

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 = 3; //변경 불가
	
	std::cout << IN << x << y << z << a; 
	return 0;
} //http://cpp.sh/

const로 지정된 변수는 값을 변경 할 수 없다.

 

const 함수 예제 소스

#include <iostream>
class Dog {
	int age; //private 생략함
public:
	int getAge() const;
	void setAge(int a) 
	{ 
		age = a; 
	}
	void view() const
	{ 
		std::cout << "나는 view\n";
	}
};
int Dog::getAge() const
{
	view(); // 오류 ① const함수는 const함수만 호출 할 수 있다.
	return age; // 오류 ② ++age는 멤버변수 값을 1 증가시키기 때문에 const함수에서는 사용 불가능하다
}
int main()
{
	Dog happy;
	happy.setAge(5);
	std::cout << happy.getAge();
	return 0;
}

const함수가 const함수만 호출 할 수 있는 이유는  일반 함수를 호출하여 멤버변수 값을 변경할 수 있기 때문에 const함수만 호출이 가능하다.

const 객체 소스

#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); // 오류 setAge()함수는 멤버변수 age를 변경하기 때문에 호출 불가
	std::cout << happy.getAge();
	return 0;
}

또는 Dog happy 앞의 const를 없애면 setAge()함수를 호출 할 수 있다.

Dog class예제 소스에서 const 사용

#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;
}

 

동적 메모리 할당

#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; // 정상 종료시 리턴값
}

 

int*pi =new int는 주소를 가르키는 포인터 변수 pi를 와 new int를 사용해 heap영역에 4바이트 int형 영역 생성 

포인터 변수 pi를 통해 heap영역에 접근한다.

Heap 영역에 메모리를 할당하고 그 주소에  pi변수가 주소의 값으로 100 할당한다.

new를 사용해 동적 메모리 할당으로 Heap영역을 사용했으면 컴퓨터가 종료되기 전까지 메모리의 Heap영역을 사용하기 때문에 반드시 delete를 사용해 메모리를 해제 해줘야 한다.

 

배열을 delete할 때에는 반드시 포인터 변수 앞에 []를 써야 한다.

 

동적메모리 할당 *중요

#include <iostream>
#include <stdlib.h> //exit(1)
int main()
{
	int i, n; //변수선언
	int* num; //포인터변수 num선언
	num = new int[3];//포인터 변수 num  heap영역에 int형 배열 3개 생성
	if (num == NULL) exit(1); //종료
	for (n = 0; n < 3; n++)
	{
		std::cout << "숫자를 입력하십시오 : ";
		std::cin >> num[n];// num의 0번 ===Heap영역의 3개의 배열 중 1번째 방을 의미함
	}
	std::cout << "당신이 입력한 숫자는: ";
	for (n = 0; n < 3; n++)
		std::cout << num[n] << ", ";// nu
	delete[] num; //[]을 생략하면?
	return 0;
}

num[n]은  new int[3]으로 생성한 메모리의 heap영역에 생성된 동적 메모리의 n번째 방과 같은 의미

예를 들어서 num[0]은 heap영역에 생성된 3칸짜리 배열의 0번째 방의 주소를 가르킨다

class의 객체 동적 할당

#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; //Dog형 포인터 변수 dp선언
	dp = new Dog; //Dog형 동적 메모리 하나 생성
	if (!dp) {
		std::cout << "메모리할당 불가!";
		return 1;
	}
	dp->setAge(5);//포인터 변수이기 때문에 ->로 setAge()함수 접근
	std::cout << "메모리에 할당된 값은 "
		<< dp->getAge() << "입니다.";
	delete dp;
	return 0;
}

 

class의 객체 배열 동적 할당

#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); //포인터변수 dp의 i번째 배열에 setAge()함수에 접근
	for (int i = 0; i < 10; i++)
		std::cout << i << "번째 객체의 나이는 " << 
		dp[i].getAge() << " 입니다. " << std::endl;//포인터변수 dp의 i번째 배열에 주소에 접근하여 값을 리턴하는 문장
	delete[]dp;
	return 0;
}

 

 

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

c++ 상속  (1) 2023.11.23
c++ 함수 중첩, 디폴트 인자  (0) 2023.11.16
C++ 클래스와 생성자, 소멸자  (0) 2023.11.02
c++ 클래스  (1) 2023.10.19
c++ 구조체, 클래스  (0) 2023.10.12