업데이트:

태그: ,

카테고리:



REF : 윤성우의 열혈 C++

new & delete

C에서 동적할당을 할때 2가지 불편한 점이 있다.

int	*ptr = (int *)malloc(sizeof(int) * 10); //10개 정수를 저장할 배열
  1. 할당할 정보를 바이트단위 크기로 전달해야한다.
  2. 반환형이 void이므로 적절한 형변환을 해줘야한다.

이런 부분을 개선하기 위해서 C++에선 new와 delete를 사용한다.

int *ptr1 = new int; //int형 변수 할당
double *ptr2 = new double; //double형 변수의 할당
int *arr1 = new int[3]; //크기 3인 int형 배열 할당
double *arr2 = new double[7]; //크기 7인 double형 배열 할당


위에 동적할당한 변수, 포인터를 해제하기 위해선 free대신 delete를 사용한다.

delete ptr1;
delete ptr2;
delete []arr1;
delete []arr2;

할당 해제하려는 변수명만 delete키워드 뒤에 써주면 되고,
배열이라면 []만 포인터 명 앞에 써주면 된다.



객체의 생성에 사용되는 new, delete

#include <iostream>
#include <stdlib.h>
using namespace std;

class Simple
{
	public:
		Simple()
		{
			cout<<"I'm simple constructor!"<<endl;
		}
};

int main()
{
	cout<<"case 1: ";
	Simple * sp1=new Simple;

	cout<<"case 2: ";
	Simple * sp2 = (Simple *)malloc(sizeof(Simple)*1);

	cout<<endl<<"end of main"<<endl;
	delete sp1;
	free(sp2);
	return 0;
}

위의 예제의 결과는

case 1: I'm simple constructor!
case 2: 
end of main

클래스와 객체, 생성자에 대해 배우진 않았지만,
클래스를 malloc으로 동적할당하면 클래스의 무언가가 할당되지 않는 것을 알 수 있다.
클래스에는 new, delete를 사용하자!



힙에 할당된 변수를 참조자로 접근하기

C++에서는 new 연산자로 할당한 메모리 공간은 변수로 간주하기 때문에,
참조자의 선언이 가능하다.

int *ptr = new int;
int &ref = *ptr;
ref = 20;
cout<<*ptr<<endl;

참조자가 가리키는 메모리 공간을 해제하기 위해선,

delete &ref;

를 해주면 된다.



C++에서 C언어 표준함수 호출하기

c를 더하고 .h를 빼기

C언어 라이브러리 (stdio.h, stdlib.h, string.h 등)에 다양한 종류의 함수가 있는데,
이런 함수는 C++의 표준 라이브러리에도 포함되어있기 때문에, 사용할 수 있다.

//c언어
#include <stdio.h> 
/*||*/ 
#include <cstdio>

#include <stdlib.h> 
/*||*/
#include <cstdlib>

#include <string.h> 
/*||*/
#include <cstring>

이렇게 헤더를 선언할 수 있다.
차이점은 헤더이름, 그리고 이름공간 std에 선언되어있다는 점이다.


C++의 헤더를 선언해야하는 이유

C++의 관점에서 기존의 C라이브러리의 함수호출을 허용하는 이유는,
하위 버전과의 호환성제공때문이다.

C++이 C보다 높은 버전의 언어니까, 하위버전인 C의 함수를 제공하는 것이다.

하지만, C의 헤더를 그대로 사용하기보다는, C++이 제공하는 C의 헤더를 사용하는게 좋은데,

그 이유는 C++의 헤더는 C++의 문법을 기반으로 C의 함수를 정의해놓았기 때문이다.

가령, math.h헤더로 호출한 함수 abs를 예로들면,

int abs(int num);

위 함수는 c에선 정수자료형을 받아서 정수형으로 반환해주는 함수이지만,

C++에서는

long abs(long num);
float abs(float num);
double abs(double num);
long double abs(long double num);

처럼 오버로딩 되어있기때문에, 인자로 넣는 자료형에 따라 알아서 절대값으로 바꿔준다.



C++에서 구조체

C언어에서는 구조체 변수를 선언하기 위해선

struct Car basiccar;
struct Car simplecar;

처럼 struct 키워드가 필요하고, 이를 생략하기 위해선 typedef로 선언해줘야한다.

하지만, C++에선 typedef없이고 구조체를 선언하면

Car basiccar;
Car simplecar;

구조체 변수를 쉽게 선언할 수 있다.


구조체 안에 함수삽입

구조체 안에 함수를 삽입하면 해당 구조체와 관련된 데이터와 함수를 모두 묶으므로
데이터간 종속성을 확실히 구분할 수 있다.

C++에서는 구조체 안에 함수를 삽입하는 것을 허용한다.

구조체 안에 함수를 삽입하게되면, 해당 구조체 변수가 가진 데이터를 함수가 직접 접근할 수 있다.

따라서, 구조체를 매개변수로 받던 함수는 더이상 매개변수로 구조체가 필요하지 않게된다.


구조체 안에 enum 상수 선언

매크로 상수들 도한 데이터 종속성에 의해 특정 구조체에게만 필요할수도 있다.
따라서, 구조체가 사용하는 상수 또한 구조체 내에 포함시키는게 더 좋을수도 있다.
이때는 enum으로 구조체 내에서만 유효한 상수를 정의할 수 있다.

struct A
{
	enum
	{
		ID_LEN	= 10
		ASD		= 20
		...
	}
}

열거형을 구조체 안에 삽입하는 것을 원하지 않는다면, 이름공간을 이용해 이름공간을 명시해줄수도 있다.

namespace	CONST_STD
{
	enum
	{
		ID_LEN	= 10
		ASD		= 20
		...
	}
}

이렇게 이름공간 내부에 열거형을 선언하면, 해당 이름공간을 명시해줘야만 열거형을 사용할 수 있다.


구조체 내부의 함수몸체는 외부로 뺄 수 있다.

구조체 내부에 함수를 정의할때, 함수의 선언만 내부에 해주고, 함수의 몸체는 다른 부분으로 뺄 수 있다.
해당 구조체가 어떤 함수를 사용할 수 있는지에 대한 로직을 직관적으로 파악할 수 있다.

struct A
{
	void	TestFunction();//함수 선언부
}

void	A::TestFunction()
{
	//몸체
}


인라인 함수로 처리

인라인 함수는 말 그대로, 함수가 호출되면 현재 line에 그대로 들어와서 처리된다.
인라인 함수는 매크로 함수보다 조금 더 똑똑하게 함수를 치환해준다.
인라인 함수의 장점으로 함수와 똑같이 생겼고, 결과도 비슷하지만,
일반적인 함수를 정의해서 사용하는 것보다 처리속도가 더 빠르다는 점이다.

구조체 내부에 함수가 정의되어있으면, 그 함수는 인라인으로 처리된다.
따라서, 해당 함수의 몸체를 위처럼 구조체 바깥으로 빼내면 인라인으로 처리되지 않는다.
그렇기 때문에, 인라인 함수로 명시적으로 처리하도록 지시해줘야한다.

inline void	A::TestFunction()
{
	//몸체
}

댓글남기기