Shared Pointer

  • shared pointer는 여러 파티(각 파티가 포인터를 갖고 있음)에서 공통으로 사용하는 메모리를 관리한다.
  • shared_ptr가 더이상 데이터를 참조하지 않는 즉시 메모리를 해제한다. ( Reference Count )
  • 프로그램을 단순하고, 동시접근가능하게 할때 사용한다.
  • 모든 스레드가 접근이 끝나면 메모리를 자동으로 해제한다.
  • shared ptr은 원하는 만큼 복사가 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <memory>
std::shared_ptr<double> f();
using namespace std;
int main()
{
std::shared_ptr<double> p = f();

cout << "p.use_count() = " << p.use_count() << endl;

// 아래의 방식으로 만들게되면, 메모리 관리 및 데이터 저장하며, 매모리 캐싱이 보다 효율적이다.
// make_shared 함수는 shared_ptr을 반환하기 때문에, 단순화된 자동 타입추론을 사용가능 (auto variable)
shared_ptr<double> p1 = make_shared<double>();

// shared_ptr은 메모리와 실행 시간에 약간의 오버헤드가 있다. 대신 프로그램을 단순화 할수 있다.
}
std::shared_ptr<double> f()
{
std::shared_ptr<double> p1{ new double };

std::shared_ptr<double> p2{ new double }, p3 = p2;
cout << "p3.use count() = " << p3.use_count() << endl;

// 함수를 반환하면 포인터를 파괴하고 p1이 참조하는 메모리를 해제한다.

// p2가 만들어지고 p3에 할당연산하면서 use count가 2가 된다.
// p3의 값이 리턴하면서 함수 반환되고 use count가 1이 된다.
return p3;
}

Unique Pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <memory>
using namespace std;
std::unique_ptr<double> f();
int main()
{
// Unique Ownership 을 나타낸다.
unique_ptr<double> dp{ new double };
*dp = 7;

// 따라서 동적으로 할당하지 않은 주소를 할당하면 버그가 발생한다.
double d;
unique_ptr<double> dd{ &d }; // 동적으로 할당되지 않은 주소를 할당함.

// Unique Ptr은 다른 포인터 타입에 할당되거나 암시적으로 변환할 수 없다.
// 원시 포인터에서 포인터의 데이터를 얻고 싶다면 get함수를 이용한다.
double *raw_dp = dp.get();

// 다른 unique_ptr에 할당할 수 없다.
// unique_ptr<double> dp2{ dp };
// dp2 = dp;
unique_ptr<double> dp2;
dp2 = f();

// unique_ptr에는 배열을 위한 구현이 있음.
// 이 작업은 메모리를 적절히 해제할 때 필요하다. 특수화를 통해 배열처럼 요소에 접근할수 있는 기능을 제공한다.
unique_ptr<double[]> da{ new double[3] };

for (unsigned i = 0; i < 3; ++i)
da[i] = i + 2;

// 그 대신에 연산자 *은 사용할수 없다.
// unique_ptr의 중요한 이점은 원시 포인터에 비해 시간과 메모리에 대한 오버헤드가 전혀 없다는 점이다.

// unique_ptr의 고급기능중에 사용자 정의 Deleter를 제공하는 기능이 있다.

return 0;
}

std::unique_ptr<double> f()
{
// 이 경우 함수의 결과는 이동될 임시 값이므로 Move Semanitcs가 필요가 없다.
return std::unique_ptr<double>{new double};
}