2024. 11. 5. 11:51ㆍC++프로그래밍/수업 내용 및 수업 후 과제
여러 프로그래밍 언어에서 new 연산자의 사용을 비교한 표
| 언어 | new 연산자 사용 예시 | 설명 |
| C++ | MyClass* obj = new MyClass(); | 동적으로 메모리를 할당하고 객체를 생성합니다. 수동으로 delete를 사용해 메모리를 해제해야 합니다. |
| Java | MyClass obj = new MyClass(); | 객체를 생성하고 생성자를 호출합니다. 가비지 컬렉터가 자동으로 메모리를 관리합니다. |
| C# | MyClass obj = new MyClass(); | 객체를 인스턴스화하고 생성자를 호출합니다. 가비지 컬렉터가 메모리를 관리합니다. 1 |
| JavaScript | let obj = new MyClass(); | 새 객체 인스턴스를 생성하고 생성자 함수를 호출합니다. 7 |
| TypeScript | let obj: MyClass = new MyClass(); | JavaScript와 유사하지만 타입 지정이 가능합니다. |
| Python | 사용하지 않음 (obj = MyClass()) | new 키워드 없이 직접 클래스를 호출하여 객체를 생성합니다. 8 |
| Go | 사용하지 않음 (obj := MyStruct{}) | 구조체 리터럴을 사용하여 객체를 생성합니다. |
C++, Java, C#, JavaScript, TypeScript 등의 언어에서는 new 연산자를 사용하여 객체를 생성
반면 Python이나 Go 같은 언어에서는 new 키워드를 사용하지 않고 다른 방식으로 객체를 생성
new 연산자의 주요 목적은 동적으로 메모리를 할당하고 객체를 생성
#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;
}
ctrl + f 찾기 + 일괄 바꾸기

배열 없애고 결과를 string형을 바꾸기 8번째 줄 확인 12번째줄 29번째 줄
const char*을 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;
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;
}
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 변수
변수에 const라는 키워드를 사용하여 상수(constant)의 의미를 갖게 하여 그 내용을 변경할 수 없게 함
#define IN 10 // 전처리기로 컴파일 전에 IN을 10로 변경
const int x=1; // 변수 x는 항상 초깃값 1,
// const를 쓰면 뒤에 x=2 이렇게 써도 초기값이 변경이 되지 않음
반드시 초깃값 필요함
int const y=1; // 비추, const는 자료형 앞에 씀
const int z{1}; // Uniform initialization, C++11
z{}라고 쓰면 자동으로 0으로 초기화
//위의 3개는 실행할 때 상수로 만들지만 아래는 ↓ 컴파일 할때 상수로 만듬
constexpr int a = 5; // C++11부터 가능, compile-time constant

실습 5-1: const형 멤버함수
오류 수정
#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;
}
① const 멤버함수는 const 함수만 호출할 수 있고, 일반 함수를 호출할 수 없다.
여기서 view함수가 const 함수라면 가능하다.
② const 멤버함수에서는 멤버변수 age를 변경(++age)할 수 없다.
① Dog::view: 'this' 포인터를'const Dog'에서'Dog &'(으)로변환할수없습니다.
② l-value가 const 개체를지정합니다.
오류 수정 완료
#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(); // 오류 ①
return age; // 오류 ②
}
int main()
{
Dog happy;
happy.setAge(5);
std::cout << happy.getAge();
return 0;
}
const 멤버
const형 멤버함수는 해당 멤버변수를 변경하는 치환 (replacement)연산을 수행할 수 없다.
const로 지정된 함수에서는 멤버변수의 값을 변경할 수 없다.
즉, 멤버를 참조만 하는 읽기 전용 함수(앞에서 get으로 시작하는 함수)가 된다.
const함수는 const함수만 호출할 수 있으며 일반 멤버함수에는 접근할 수 없다.
일반 멤버함수에 접근하여 간접적으로 멤버변수를 변경하는 것을 막기 위해 생성자와 소멸자에서는 const를 사용할 수
없다.
const형을 선언하고자 하면 멤버변수는 형 앞에 const를, 멤버함수는 함수의 괄호 다음에 const를 추가한다.
const int age; //멤버변수는 형 앞에
int getAge() const; //멤버함수는 괄호 다음에
int getAge()
{
return age;
}
실습 5-2: 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); // 오류
std::cout << happy.getAge();
return 0;
}
• Happy.setAge(7); 생략
• const 객체 happy에는 const로 지정된 멤버함수만 호출할 수 있다.
• 해당 클래스의 어떠한 멤버변수도 바꾸지 않는 멤버함수(get으로 시작하는 함수)는 const형으로 선언하는 것이 좋다.
• 이렇게 하면 컴파일러가 오류를 찾는데 도움을 줄 수 있다.
위의 코드 오류 수정
#include <iostream>
class Dog {
int age;
public:
Dog(int a) : age(a) {} // 초기화 리스트 사용
int getAge() const { return age; }
void setAge(int a) { age = a; }
void view() const
{
std::cout << "나는 view\n";
}
};
int main()
{
const Dog happy(5); // const 객체
// happy.setAge(7); // 오류 - 주석 처리 또는 제거
std::cout << happy.getAge();
return 0;
}
오류 설명 및 수정사항
주요 오류: happy.setAge(7);
문제: happy는 const 객체로 선언되었기 때문에, 비-const 멤버 함수인 setAge()를 호출할 수 없다.
해결: 이 라인을 주석 처리하거나 제거했습니다. const 객체의 값은 변경할 수 없습니다.
추가 개선사항
생성자 초기화 리스트 사용:
cpp
Dog(int a) : age(a) {}
이는 멤버 변수를 초기화하는 더 효율적인 방법
getAge() 함수 인라인화:
cpp
int getAge() const { return age; }
작은 함수의 경우 인라인으로 정의하는 것이 일반적입니다.
Dog::getAge() 함수의 별도 정의 제거:클래스 내부에서 직접 정의했으므로,클래스 외부의 정의는 불필요
이러한 수정을 통해 코드는 이제 C++ 컴파일러에서 오류 없이 컴파일되며,const 정확성(const correctness)을 준수.
const 객체는 오직 const 멤버 함수만 호출할 수 있으며,이는 객체의 상태가 변경되지 않음을 보장
포인터 개요
포인터(pointer)는 C/C++ 언어를 다른 언어와 차별화시키는 가장 큰 특징
포인터를 이용하게 되면 기계어나 어셈블리 언어처럼 메모리의 주소를 이용해 메모리의 내용을 직접 접근할 수 있음
포인터가 사용되는 경우
- call by reference로 함수로부터 한 개 이상의 값을 리턴할 때
- 함수들 간에 배열이나 문자열을 전달할 때
- 배열 조작을 쉽게 할 때
- 연결 리스트(linked list)나 이진 트리(binary tree) 등 복잡한 자료 구조를 만들 때
- 메모리를 동적으로 할당할 때
int *pi=(int*)malloc(100*sizeof(int)); //C
int *pi=new int[100]; //C++
x와 x의 주소
#include <iostream>
int main()
{
int x = 1;
std::cout << x << " " <<&x;
return 0;
}
결과
1 0000009E990FF8B4(주소는 스택의 주소라 매번 다르게 나옴)
포인터와 주소
메모리에는 위치를 구분하기 위해 순서대로 번호가 붙어있는데 이것을 메모리의 주소, 번지, address라 함
int sum=0;
- 변수를 초기화하면서 선언하면, int형이므로 4바이트 메모리 공간이 확보되고 초기값으로 0이 할당됨
- sum변수가 실제로 할당된 메모리의 주소를 알고 싶다면 &연산자를 사용하여
&sum이라고 하면 변수가 기억되어 있는 메모리 번지를 알 수 있음
메모리의 주소를 저장하려면 일반 변수가 아닌 포인터를 사용
포인터라고만 해도 되지만 주소를 저장하는 변수이므로 포인터 변수라고도 함
#include <iostream>
int main()
{
int x = 1;
int *px = &x; // 주소는 포인터 변수로 저장해야함
// 따라서 px 앞에 *을 써서 포인터 변수로 선언
// 포인터 변수는 주소만 넣을 수 있음
std::cout << x << " " << &x << " " << *px;
return 0;
}
------------------------
코드 설명
`#include <iostream>`: 표준 입출력 라이브러리 포함.
`int main()`: 프로그램 진입점.
`int x = 1;`: 정수형 변수 x 선언 및 초기화.
`int *px = &x;`: 포인터 변수 선언. x의 주소 저장.
`std::cout << x << " " << &x << " " << *px;`: 출력문.
- x: 변수 값 출력.
- &x: 변수 주소 출력.
- *px: 포인터가 가리키는 값 출력.
`return 0;`: 프로그램 정상 종료 표시.
포인터 개념 설명:
- 변수: 메모리 상 주소 보유.
- &: 주소 연산자.
- 포인터: 주소 저장 변수.
- *: 역참조 연산자.
프로그램 기능: 변수 값, 주소, 포인터 통한 값 접근 예시.
포인터 변수의 자료형?
자료형 *포인터변수명;
int *pi;
- 변수 pi가 int형 데이터를 참조하기 위한 포인터 변수
- pi가 지시하는 곳의 자료형이 int형
char *pc;
- 변수 pc가 char형 데이터를 참조하기 위한 포인터 변수
- pc가 지시하는 곳의 자료형이 char형


정적 vs. 동적 메모리 할당
정적 메모리 할당
- 컴파일시 필요한 메모리 할당
- 배열 : int array[32]; // 항상128byte 공간 확보
- 사용하지 않는 메모리까지 충분히 잡아 낭비
- 너무 큰 메모리는 할당 불가
- 보통 수 kB까지는 스택 사용, 그 이상은 heap에 할당
- Windows(Visual Studio)에서 기본 스택 크기는 1MB
- Linux와 macOS에서 기본 스택의 크기는 8MB
동적 메모리 할당
- 실행시 필요한 메모리(heap) 할당
- 필요한 만큼만 잡음
- 메모리의 주소를 사용(포인터 이용)하여 접근
- malloc()/free() 사용 // C
- new/delete사용 // C++
- new : 메모리 할당, 할당된 메모리 시작주소 리턴됨
- delete : 할당 받은 메모리 해제


실습 5-4: 동적메모리 할당(필요한 만큼의 메모리만 실행시 할당)
기말고사에 나올 확률이 있음
#include <iostream>
#include <stdlib.h> // exit() 함수를 사용하기 위한 헤더
int main()
{
int i, n;
int* num; // num에는 주소만 저장,
// 포인터 변수 선언. 동적 할당된 배열의 시작 주소를 저장할 예정
// 배열로 쓰고 있는데 배열이 아닌 포인터로 선언되어 있음
std::cout << "몇 개의 숫자를 입력하시겠습니까==";
std::cin >> i;
num = new int[i]; // 동적으로 int 배열 할당. num은 배열의 첫 번째 요소 주소를 가리킴
if (num == NULL) exit(1); // 메모리 할당 실패 시 프로그램 종료
// 대괄호가 나온 것은 배열
// 배열로 쓰고 있는데 배열이 아닌 포인터로 선언되어 있음
// 배열의 이름은 그 배열의 시작 주소이다.
// 사용자로부터 숫자 입력 받기
for (n = 0; n < i; n++)
{
std::cout << "숫자를 입력하십시오 : ";
std::cin >> num[n]; // 포인터를 배열처럼 사용. num[n]은 *(num+n)과 동일
}
// 입력받은 숫자 출력
std::cout << "당신이 입력한 숫자는: ";
for (n = 0; n < i; n++)
std::cout << num[n] << ", ";
delete[] num; // 동적 할당된 배열 메모리 해제. []를 생략하면 첫 번째 요소만 해제됨
return 0;
}
이 코드의 동작 과정
1. 프로그램 시작:
main() 함수 실행 시작.
2. 사용자 입력 요청:
"몇 개의 숫자를 입력하시겠습니까==" 메시지 출력.
사용자로부터 정수 i 입력 받음.
3. 동적 메모리 할당:
new int[i]로 i개의 정수를 저장할 수 있는 배열 동적 생성.
생성된 배열의 시작 주소를 num 포인터에 저장.
4. 메모리 할당 확인:
할당 실패 시(num == NULL) 프로그램 종료.
5. 숫자 입력 루프:
for 루프로 i번 반복.
각 반복마다 사용자에게 숫자 입력 요청.
입력된 숫자를 num[n]에 저장 (n은 0부터 i-1까지).
6. 입력된 숫자 출력:
"당신이 입력한 숫자는: " 메시지 출력.
for 루프로 num 배열의 모든 요소 출력.
각 숫자 뒤에 쉼표와 공백 추가.
7. 메모리 해제:
delete[] num으로 동적 할당된 메모리 해제.
8. 프로그램 종료:
return 0으로 main() 함수 종료.
주요 특징:
- 동적 메모리 할당으로 런타임에 배열 크기 결정.
- 포인터를 배열처럼 사용.
- 사용자 입력에 따라 유동적으로 메모리 사용.
이 코드는 사용자가 지정한 개수만큼의 숫자를 입력받고 출력하는 간단한 프로그램.
동적 메모리 할당의 기본적인 사용법 예시.
실습 5-5: 객체 동적할당
#include <iostream>
class Dog {
private:
int age;
public:
int getAge() const;
void setAge(int a);
};
int Dog::getAge() const
{
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; //delet 쓰는것 매우 중요
return 0;
}
실습 5-6: 배열객체 동적 할당
```cpp
#include <iostream>
class Dog {
private:
int age;
public:
int getAge() const; // const 추가: 객체의 상태를 변경하지 않음을 명시
void setAge(int a);
};
int Dog::getAge() const // const 추가: 선언과 일치
{
return age;
}
void Dog::setAge(int a)
{
age = a;
}
int main()
{
Dog* dp;
dp = new Dog[10]; // 10개의 Dog 객체 배열 동적 할당
// dp를 배열처럼 씀
if (!dp) {
std::cout << "메모리할당이 되지 않았습니다.";
return 1; // 메모리 할당 실패 시 프로그램 종료
}
// 각 Dog 객체의 나이 설정
for (int i = 0; i < 10; i++)
dp[i].setAge(i);
// 각 Dog 객체의 나이 출력
for (int i = 0; i < 10; i++)
std::cout << i << "번째 객체의 나이는 "
<< dp[i].getAge() << " 입니다. " << std::endl;
delete[] dp; // 배열 형태로 할당된 메모리 해제
return 0;
}
```
주요 수정 및 설명:
1. `getAge()` 함수에 `const` 추가:
- 클래스 선언과 정의 모두에 `const` 추가.
- 이는 함수가 객체의 상태를 변경하지 않음을 보장.
2. 주석 추가:
- 코드의 주요 부분에 설명 추가.
- 동적 할당, 객체 배열 사용, 메모리 해제 등 설명.
3. 메모리 할당 확인:
- `if (!dp)` 문으로 메모리 할당 실패 시 처리.
4. 배열 형태의 메모리 해제:
- `delete[] dp`로 올바르게 배열 메모리 해제.
이 코드는 Dog 객체의 배열을 동적으로 생성하고, 각 객체의 나이를 설정한 후 출력하는 예제
`const` 정확성을 개선하고, 메모리 관리를 적절히 수행
const 함수를 지정할 수 있는건 지정해서 소스를 보기 편하게 함.
#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;
}
동적으로 할당하게 되면 heap라는 공간에 할당'C++프로그래밍 > 수업 내용 및 수업 후 과제' 카테고리의 다른 글
| C++ 12주차 수업 내용 및 수업 후 과제 (1) | 2024.11.19 |
|---|---|
| C++ 수업내용 및 수업 후 과제 (0) | 2024.11.12 |
| c++ 9주차 수업 내용 및 수업 후 과제 (0) | 2024.10.29 |
| C++ 7주차 수업 내용 및 수업 후 과제 (0) | 2024.10.15 |
| c++ 5주차 비대면 수업 (0) | 2024.10.07 |