new 연산자를 사용하는 프로그래밍 언어:
C++: 객체를 동적으로 생성할 때 new 키워드를 사용합니다.
Java: 객체를 생성할 때 new 연산자를 사용하며, 메모리를 할당합니다.
C#: 객체 인스턴스를 생성할 때 new 키워드를 사용합니다.
JavaScript: 생성자 함수나 클래스를 통해 객체를 만들 때 new 키워드를 사용합니다.
PHP: 객체를 생성할 때 new 키워드를 사용합니다.
동적으로 메모리를 할당한다는 것은 컴퓨터가 필요할 때마다 메모리를 사용할 수 있도록 요청하는 것을 의미함.
예를 들어, 우리가 책을 읽을 때, 필요한 페이지를 한 장씩 넘겨서 읽는 것처럼, 프로그램도 필요할 때마다 메모리를 요청해서 사용하는 것이 필요함
이렇게 하는 이유는:
효율성: 프로그램이 필요할 때만 메모리를 사용하니까, 메모리를 낭비하지 않음
유연성: 프로그램이 실행되는 동안 필요한 메모리의 양이 변할 수 있어. 예를 들어, 게임에서 새로운 캐릭터가 추가될 때마다 메모리를 더 요청 가능
자동 관리: 프로그램이 끝나면 사용했던 메모리를 자동으로 반환할 수 있어서, 메모리를 깔끔하게 관리 가능
비쥬얼 스튜디오에서 한 번에 바꾸기
컨트롤 + f + h
⭐이름을 배열에 저장해서 받는 코드
⭐이름을 배열에 저장해서 받는 코드
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string> //strcpy에서 오류나면 string.h로 변경
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;
}
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;
}
⭐배열을 안쓰고 std::string형을 써서 더 편하게
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string> //strcpy에서 오류나면 string.h로 변경
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; // 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;
}
void Cat::setName(std::string pName) {
name, pName;
//strcpy(대상주소, 원본주소);
//strcpy_s(대상주소, 대상의길이, 원본주소);
//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;
}
변수를 상수로 만드는 방법
우선 변수로 만들고
바꾸고 싶지 않으면 const로 만들고 상수화 한다
초기값에서 -> 변경하는 형식
오류 수정 코드
#include <iostream>
class Dog {
private:
int age; // private으로 선언
public:
int getAge() const; // const 메서드
void setAge(int a) { age = a; }
void view() const { // const 메서드로 변경
std::cout << "나는 view\n";
}
};
int Dog::getAge() const {
view(); // 오류 ① 수정
return age; // 오류 ② 수정: age를 증가시키지 않음
}
int main() {
Dog happy;
happy.setAge(5);
std::cout << happy.getAge(); // 5 출력
return 0;
}
실습 소스
#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;
}
⭐(중요/어려움) 포인터 개요
C++에서 변수의 값과 주소를 출력하는 프로그램
결과가 계속 바뀜
포인터 변수 선언
첫 번째 코드
#include <iostream>
int main() {
int x = 1; // 정수형 변수 x를 1로 초기화
int* px = &x; // x의 주소를 px 포인터 변수에 저장
std::cout << x << " " << &x << " " << px; // x의 값, x의 주소, px의 값(주소)을 출력
return 0;
}
출력 내용:
x: 변수 x의 값 (1)
&x: 변수 x의 메모리 주소
px: 포인터 px가 가리키는 주소 (즉, x의 주소)
두 번째 코드
#include <iostream>
int main() {
int x = 1; // 정수형 변수 x를 1로 초기화
int* px = &x; // x의 주소를 px 포인터 변수에 저장
std::cout << x << " " << &x << " " << *px; // x의 값, x의 주소, px가 가리키는 값(즉, x의 값)을 출력
return 0;
}
출력 내용:
x: 변수 x의 값 (1)
&x: 변수 x의 메모리 주소
*px: 포인터 px가 가리키는 값 (즉, x의 값인 1)
요약
주요 차이점:
첫 번째 코드에서는 px를 출력하여 포인터가 가리키는 메모리 주소를 보여줍니다.
두 번째 코드에서는 *px를 출력하여 포인터가 가리키는 값 (즉, x의 값)을 보여줍니다.
그림으로 보기 (파이썬 튜텨)
포인터는 변수의 주소를 가리키고, 그 주소를 통해 값 저장함
동적 메모리 할당
⭐⭐⭐(필수/시험 무조건 나옴) 동적 메모리를 사용하는 이유
C++ 코드는 정적 할당과 동적 할당의 차이를 보여주는 예제
주어진 C++ 코드는 정적 할당과 동적 할당을 사용하는 예시
동적 할당에서 new 연산자를 사용하여 초기값을 설정하는 방법
동적 메모리의 팔당과 해제 : new 와 delete
동적 할당된 메모리를 사용한 후 올바르게 해제하는 예제 (delete)
배열로 할당과 삭제 (대괄호 주의)
(중요/ 시험 예상문)
#include <iostream>
#include <stdlib.h> // exit(1) 사용을 위한 헤더
int main() {
int i, n; // 정수형 변수 i, n 선언
int *num; // 정수형 포인터 num 선언
std::cout << "몇 개의 숫자를 입력하시겠습니까?=";
std::cin >> i; // 사용자로부터 입력받은 숫자를 i에 저장
num = new int[i]; // i개의 정수를 저장할 동적 배열 할당
if (num == NULL) exit(1); // 메모리 할당 실패 시 종료
for (n = 0; n < i; n++) { // 0부터 i-1까지 반복
std::cout << "숫자를 입력하십시요: ";
std::cin >> num[n]; // 사용자로부터 입력받은 숫자를 배열에 저장
}
std::cout << "당신이 입력한 숫자는: ";
for (n = 0; n < i; n++) { // 0부터 i-1까지 반복
std::cout << num[n] << " "; // 저장된 숫자를 출력
}
delete[] num; // 동적 메모리 해제
return 0; // 프로그램 종료
}
⭐⭐(중요 / 시험 확정 문제)배열의 이름은 배열의 시작주소
포인터 객체는 *이 아니고, -> 로 접근한다.
#include <iostream>
class Dog {
private:
int age; // 개의 나이를 저장할 private 멤버 변수
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 = new Dog[10]; // Dog 객체 배열 동적 할당
// 메모리 할당 실패 시 처리
if (!dp) {
std::cout << "메모리 할당이 되지 않았습니다.";
return 1;
}
// 각 Dog 객체의 나이를 설정
for (int i = 0; i < 10; i++) {
dp[i].setAge(i); // i번째 객체의 나이를 i로 설정
}
// 각 Dog 객체의 나이를 출력
for (int i = 0; i < 10; i++) {
std::cout << i << "번째 객체의 나이는 " << dp[i].getAge() << " 입니다." << std::endl;
}
delete[] dp; // 동적 할당된 메모리 해제
return 0; // 프로그램 종료
}
배열 객체 동적 할당
#include <iostream>
// Dog 클래스 정의
class Dog {
private:
int age; // 개의 나이를 저장하는 private 멤버 변수
public:
int getAge(); // age를 반환하는 public 멤버 함수
void setAge(int a); // age를 설정하는 public 멤버 함수
};
// Dog 클래스의 getAge() 멤버 함수 정의
int Dog::getAge()
{
return age; // private 멤버 변수 age의 값을 반환
}
// Dog 클래스의 setAge() 멤버 함수 정의
void Dog::setAge(int a)
{
age = a; // 매개변수 a의 값을 private 멤버 변수 age에 할당
}
int main()
{
Dog *dp; // Dog 객체를 가리키는 포인터 선언
dp = new Dog[10]; // 10개의 Dog 객체를 동적으로 할당하여 배열 생성
// 위 문장은 다음과 같이 한 줄로 작성할 수도 있음: Dog *dp = new Dog[10];
// 메모리 할당 실패 체크
if(!dp) {
std::cout << "메모리할당이 되지 않았습니다.";
return 1; // 프로그램 비정상 종료
}
// 각 Dog 객체의 나이를 설정 (0부터 9까지)
for(int i = 0; i < 10; i++) // C++에서는 동적 할당된 객체 배열도 []로 접근 가능
dp[i].setAge(i);
// 각 Dog 객체의 나이를 출력
for(int i = 0; i < 10; i++)
std::cout << i << "번째 객체의 나이는 "
<< dp[i].getAge() << " 입니다. " << std::endl;
delete[] dp; // 동적으로 할당된 메모리 해제 (배열 형태로 할당했으므로 delete[]를 사용)
return 0; // 프로그램 정상 종료
}
#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 happy;
dp = new Dog; // Dog *dp=new Dog
if (!dp) {
std::cout << "메모리할당 불가!";
return 1;
}
happy.setAge(3);
std::cout << happy.getAge();
dp->setAge(5); //dp는 포인터 객체라 ->로 접근
std::cout << "메모리에 할당된 값은 "
<< dp->getAge() << "입니다.";
delete dp;
return 0;
}
고양이 배열 객체 동적 메모리 할당
#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();
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;
}
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;
cout << pNabi->getName() << " 출생 나이는 " << pNabi->getAge() << "살이다.\n";
nabi.setName("Nabi");
nabi.setAge(3);
cout << nabi.getName() << " 나이는 " << nabi.getAge() << "살이다.\n";
yaong.meow();
nabi.meow();
return 0;
}