반응형
결론: C++11에선 걍 std::vector 쓰세요.
std::shared_ptr로 배열을 동적할당 해보겠습니다.
| 코드 1 - 잘못된 배열 생성 |
// [코드 1: 잘못된 배열 생성]
// C++11이상에서 동작합니다.
#include <iostream>
#include <memory>
using namespace std;
int main() {
struct A {
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
};
shared_ptr<A> array(new A[10]);
}
너무나 실행이 잘됩니다. 그러나, 치명적인 문제가 있습니다.
10개의 요소를 생성했으나 맨 처음의 한 개만 제거되고 나머지는 그대로 남게됩니다.
클래스 내부에서 delete[] 가 아닌 delete로 삭제했기 때문이죠.
이를 위해, shared_ptr는 배열을 삭제할 수 있는 방법을 줍니다.
| 코드 2 - 올바른 배열 생성 (1) |
// [코드 2: 올바른 배열 생성 (1) ]
// C++11이상에서 동작합니다.
#include <iostream>
#include <memory>
using namespace std;
int main() {
struct A {
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
};
shared_ptr<A> array(new A[10], [](A* a) {
delete[] a;
});
}
예, 이제 해제가 아주 잘 됩니다. 하지만 저렇게 매번 타입을 적기는 귀찮습니다.
C++14의 제네릭 람다를 이용하면 어떨까요?
shared_ptr<A> array(new A[10], [](auto a) { delete[] a; })
auto, 좋습니다. 아주 좋아요.
하지만! 이렇게 람다를 매번 정의하고 넘기는것 자체가 귀찮습니다.
그래서 C++17에선 파격적인 문법을 제공합니다.
타입을 T가 아닌 T[]로 기술하는 겁니다.
| 코드 3 - 올바른 배열 생성 (2) |
// [코드 3: 올바른 배열 생성 (2) ]
// C++17이상에서 동작합니다.
#include <iostream>
#include <memory>
using namespace std;
int main() {
struct A {
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
};
shared_ptr<A[]> array(new A[10]);
}
타입도 적기 귀찮지 않나요? 소스코드 위에 이것들을 적어주세요.
template<class T> shared_ptr(T*) -> shared_ptr<T>;
template<class T> shared_ptr(T*[]) -> shared_ptr<T[]>;
이걸 적으면 다음과 같이 템플릿 인자를 아예 생략해도 알아서 만들어줍니다.
shared_ptr array(new A[10]);
그러니까, shared_ptr array(new A[10]) 이나, vector array(10)이나 다 거기서 거기라고 볼 수 있습니다. 차이점이라면 배열과 포인터 정도?
위 코드에 대한 설명은 아래 링크를 참고하세요.
반응형
'C++ > C++ 심화 강좌' 카테고리의 다른 글
[C++17 심화 강좌] 스마트 포인터 편리하게 사용하기 (0) | 2022.02.16 |
---|---|
[C++ 심화 강좌] C++20 <=> Three-way 비교 연산자 (0) | 2021.09.22 |