본문 바로가기
Program Language/c++

c++ 기초(스마트 포인터)

by 토담이아빠 2023. 1. 13.

스마트 포인터

 

이글은 "전문가를 위한 c++(개정4)" 학습한 내용을 직접 실습해보며 정리한 Review 글입니다.


스마트 포인터

 

스마트 포인터는 delete나 delete[]를 사용할 필요가 없이 자동으로 메모리를 해제 시킵니다. c++에서 가장 중요한 스마트 포인터 타입은 다음 두 가지입니다. 


#include<memory>

std::unique_ptr
std::shared_ptr

unique_ptr은 가리키는 객체를 일반 포인터로 가리킬 수 없을 뿐만 아니라 동일 타입의 unique_ptr로도 가리킬 수 없습니다. 이는 복사생성자와 대입연산자가 구현이 되어 있지 않기 때문입니다. 

 

unique_ptr의 생성할 때는 두 가지 방법이 있습니다. 


#include <iostream>
#include <memory> //스마트 포인터 사용을 위해
 
using namespace std;
 
int main()
{
	//unique_ptr 생성하는 첫번째 방법
	unique_ptr<int> uniquePointer1(new int);
	*uniquePointer1 = 10;
	cout << "첫번째 방법으로 생성한 값 : " << *uniquePointer1 << endl;
 
	//unique_ptr 생성하는 두번째 방법
	auto uniquePointer2 = make_unique<int>();
	*uniquePointer2 = 10;
	cout << "두번째 방법으로 생성한 값 : " << *uniquePointer2 << endl;
 
	return 0;
}

결과

첫번째 방법으로 생성한 값 : 10
두번째 방법으로 생성한 값 : 10

첫번째 방법은 c++14 이전에 사용해 왔던 방식입니다. 타입을 두번 적어야하는 불편함이 있습니다. 두번째 방법은 c++14 이후에 추가된 방법입니다. 스마트 포인터의 사용법은 일반 포인터의 사용법과 같습니다. 위 예시에서 사용한 역참조 방식도 일반 포인터 역참조 방식과 동일하며 클래스나 구조체일 경우 ->연산자로 멤버에 접근할 수 있습니다.

 

unique_ptr는 배열을 생성할 수 있습니다. 배열을 생성하는 방법은 다음과 같습니다.


long arraySize = 1000;
auto myArrayBuffer = make_unique<int[]>(arraySize);

또 다른 방법은 c++17이후에 나온 방법입니다. 다음 예제 처럼 int 에 배열 연산자 []를 붙여서 int[]로 선언하는 방법입니다.


long arraySize = 1000;
unique_ptr<int[]> myArrayBuffer(new int[arraySize]);

shared_ptr도 사용법은 unique_ptr과 유사합니다. 차이점은 복사생성자와 대입연산자가 정의되어 있어서 데이터를 공유할 수 있습니다. 그리고 shared_ptr에 대한 대입연산이 발생할 때 마다 레퍼런스 카운트가 하나씩 증가합니다. 레퍼런스 카운트는 shared_ptr이 가리키는 횟수를 의미합니다.즉 횟수만큼 데이터를 소유하고 있다는 뜻입니다. shared_ptr이 스코프를 벗어나면 레퍼런스 카운트가 감소합니다. 그러다가 카운트가 0이되면 그때 객체를 해제합니다. 

 

포인터 생성방법도 unique_ptr 처럼 두가지 방식으로 생성합니다.


#include <iostream>
#include <memory> 
 
using namespace std;
 
int main()
{
	shared_ptr<int> sharedPointer1(new int);
	*sharedPointer1 = 10;
	cout << "첫번째 방법으로 생성한 값 : " << *sharedPointer1 << endl;
 
	auto sharedPointer2 = make_shared<int>();
	*sharedPointer2 = 20;
	cout << "두번째 방법으로 생성한 값 : " << *sharedPointer2 << endl;
 
 
	return 0;
}

결과

첫번째 방법으로 생성한 값 : 10
두번째 방법으로 생성한 값 : 20

shared_ptr도 배열을 생성할 수 있습니다. 하지만 unique_ptr와는 다르게 make_shared()로는 생성할 수 없습니다.

unique_ptr에서 배열을 생성했던 c++17 이후에 나온 두번째 방식으로 가능합니다.


long arraySize = 1000;
shared_ptr<int[]> myArrayBuffer(new int[arraySize]);

다음은 위 방식으로 작성한 예제입니다.


#include <iostream>
#include <memory> 
 
using namespace std;
 
int main()
{
	long arraySize = 1000;
	shared_ptr<int[]> myArrayBuffer(new int[arraySize]);
 
	for(int i = 0; i < arraySize; i++) {
		myArrayBuffer[i] = i; // 배열에 값 대입
	}
 
	//일부 배열 값을 출력한다.
	for(int i = 20; i < 30; i++) {
		cout << "index" << i << " : " << myArrayBuffer[i] << endl;
	}
 
	return 0;
}

결과

index20 : 20
index21 : 21
index22 : 22
index23 : 23
index24 : 24
index25 : 25
index26 : 26
index27 : 27
index28 : 28
index29 : 29

 

'Program Language > c++' 카테고리의 다른 글

c++ 기초(레퍼런스)  (1) 2023.01.17
c++ 기초 (const 키워드의 사용법)  (4) 2023.01.16
c++ 기초(동적 배열 할당)  (0) 2023.01.13
c++ 기초(포인터 사용법)  (0) 2023.01.12
c++ 기초(스택과 힙)  (0) 2023.01.11

댓글