unique ptr은 exclusive ownership을 보장함.
c++ heap 메모리 생성, 해제
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#include <iostream>
#include <memory>
#include <vector>
class Cat
{
public:
explicit Cat(int age) :mAge{ age }
{
std::cout << "cat constructor" << std::endl;
}
~Cat() noexcept
{
std::cout << "cat destructor" << std::endl;
}
private:
int mAge;
};
class ThiefCat
{
public:
explicit ThiefCat() : mAge{ 0 }
{
std::cout << "Thiefcat constructor" << std::endl;
}
~ThiefCat() noexcept
{
std::cout << "Thiefcat destructor" << std::endl;
}
private:
int mAge;
};
void foo()
{
std::cout << "foo function" << std::endl;
std::unique_ptr<Cat> catPtr = std::make_unique<Cat>(3);
std::cout << "foo function end" << std::endl;
};
int main()
{
//Cat* catPtr = new Cat{ 3 };
//delete catPtr;
std::cout << "before scope" << std::endl;
{
std::unique_ptr<Cat> catPtr = std::make_unique<Cat>(3);
}
std::cout << "after scope" << std::endl;
foo();
ThiefCat* thiefcats = new ThiefCat[5];
delete[] thiefcats;
//vector 쓰면 leak 안 생김
std::vector<ThiefCat> thiefcats1(10);
return 0;
}
|
cs |
ㅎ
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
///
/// //std::unique_ptr<Cat> catPtr1 = catPtr;
// unique pointer는 복사가 불가능함
// 그러나 move는 가능함
// class에서 member variable로 unique_ptr쓸때 좋음
///
#include <iostream>
#include <memory>
class Animal
{
};
class Cat : public Animal
{
public:
Cat() :mAge{ 0 }
{
std::cout << "cat constructor" << std::endl;
}
~Cat()
{
std::cout << "cat destructor" << std::endl;
}
private:
int mAge;
};
class Dog : public Animal
{
};
class Zoo : public Animal
{
public:
Zoo(int n)
{
// enum class를 사용하는 것이 더 올바르다
if (n == 1)
{
mAnimal = std::make_unique<Cat>();
}
else
{
mAnimal = std::make_unique<Dog>();
}
}
// 멤버 Variable에 포인터가 있으면 copy, move 다 정의해 주어야 함
// unique_ptr을 사용함으로써 destructor, delete, copy, move를 개발자가
// 생각할 필요가 없어짐
private:
std::unique_ptr<Animal> mAnimal;
};
void foo(Cat * ptr)
{
Cat* fooPtr = ptr;
}
int main()
{
//Cat* catPtr = new Cat();
//Cat* Catptr1 = catPtr;
//foo(catPtr);
//delete catPtr;
std::unique_ptr<Cat> catptr = std::make_unique<Cat>();
//std::unique_ptr<Cat> catPtr1 = catPtr;
// unique pointer는 복사가 불가능함
// 그러나 move는 가능함
std::unique_ptr<Cat> catptr1 = std::move(catptr);
return 0;
}
|
Shared Pointer
shared_ptr은 하나의 object를 여러개의 pointer가 가르킬 수 있음.
shared_ptr은 object를 가르키는 pointer가 증가할 때마다 reference count가 증가한다.
그러다가 reference count가 0이 되는 순간 heap 메모리에서 제거되게 된다.
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#include <iostream>
#include <memory>
class Cat
{
public:
Cat() :mAge{ 0 }
{
std::cout << "cat constructor" << std::endl;
}
~Cat()
{
std::cout << "cat destructor" << std::endl;
}
std::shared_ptr<Cat> mVar;
std::shared_ptr<Cat> mFriend;
private:
int mAge;
};
int main()
{
/// <summary>
/// 몇개의 pointer가 object를 가르키는지 명확하지 않음
/// shared pointer를 쓰자!
/// </summary>
/// <returns></returns>
Cat* catPtr = new Cat();
Cat* catPtr1 = catPtr;
delete catPtr;
/// <summary>
///
///
/// </summary>
/// <returns></returns>
std::shared_ptr<Cat> catPtr_shared = std::make_shared<Cat>();
std::cout << "count: " << catPtr_shared.use_count() << std::endl;
std::shared_ptr<Cat> catPtr_shared1 = catPtr_shared;
std::cout << "count: " << catPtr_shared.use_count() << std::endl;
/// <summary>
/// shared_ptr을 사용하지만 memory leak이 발생할 수도 있음.
/// </summary>
/// <returns></returns>
std::shared_ptr<Cat> mPtr = std::make_shared<Cat>();
mPtr->mVar = mPtr;
std::cout << "count: " << mPtr.use_count() << std::endl;
// count는 2 이며 memory leak 발생!(Destructor 미호출)
// Destructor 미호출
// pkitty, pnabi의 reference count가 서로 1이 되어서
// Destructor 미호출, memory leak 발생함
// circular reference
// Java, c#, python은 Gabage collector가 memory leak 없애줌
// Gc - "Mark and sweep" 에서 메모리 해제 방법 참고
std::shared_ptr<Cat> pKitty = std::make_shared<Cat>();
std::shared_ptr<Cat> pNabi = std::make_shared<Cat>();
pKitty->mFriend = pNabi;
pNabi->mFriend = pKitty;
return 0;
}
|
unique_ptr, 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#include <iostream>
#include <memory>
// Shared ptr을 쓰면 memory leak을 피할 수 없다.
// Cat has shared ptr member라고 표기해 줘야 한다
// 그리고 shared ptr이라면 copy가 어려우므로
// clone 함수를 별도로 만드는 게 좋다 (Ex)opencv)
class Cat
{public:
//explicit Cat(int n) : mVar{ std::make_unique<int>(n) }
explicit Cat(int n) : mVar{ std::make_shared<int>(n) }
{
std::cout << "cat Constructor" << std::endl;
}
// unique ptr만 쓰면 대입 연산이 불가능하므로(first created ownership)
// 복사 생성자를 만들어서 써야 한다.
Cat(const Cat& other) :mVar{ std::make_unique<int>(*other.mVar) }
{
std::cout << "other cat constructed" << std::endl;
}
// shared ptr을 위한 clone 함수 생성
Cat clone()
{
Cat tmp{ *mVar };
return tmp;
}
~Cat() noexcept
{
std::cout << "cat destructor" << std::endl;
}
private:
//std::unique_ptr<int> mVar;
std::shared_ptr<int> mVar;
// 만약 shared_ptr이라면 memory leak을 피할 수 없다.
// 따라서 클래스 위에
// Cat has shared ptr member라고 표기해 줘야 한다
};
int main()
{
const Cat kitty{ 1 };
//Cat nabi;
//nabi = kitty; // error(unique pointer이므로)
const Cat nabi{ kitty };
}
|
'C' 카테고리의 다른 글
c++ lambda expression, capture =, & (0) | 2021.06.23 |
---|---|
c++ weak pointer 정리 (0) | 2021.06.23 |
c++ const, explicit (0) | 2021.06.23 |
c++ class function overloading, 연산자(operator) 임의 지정 (0) | 2021.06.23 |
C++ class copy move constructor, instructor (0) | 2021.06.23 |