일반적으로 리소스를 관리하는 모든 클래스는 복사 할 수 없거나 특수한 복사 의미 체계가 있어야합니다. 그 반대의 경우도 마찬가지입니다. 복사 할 수 없거나 특수화 된 복사 의미 체계가 필요한 클래스는 자원을 관리합니다. 실제로 C++ 링구아에서 "리소스 관리"란 메모리, 네트워크 또는 데이터베이스 연결, 파일 핸들 또는 트랜잭션 실행 취소 등을 담당합니다.
리소스 관리는 많은 예제를 캡처합니다. 이것들은 접두어 연산, 접미어 연산 및 그 사이의 어떤 동작을 취하는 책임입니다. 예를 들어, 메모리 관리는 우리가 관리 할 메모리 주소에 대한 핸들을 획득하고, 아마도 그 메모리로 엉망으로 처리하고, 마지막으로 핸들을 해제하는 작업을 포함합니다.
template<typename T>
struct memory {
memory(T const& val = T()) : p(new T(val)) { }
~memory() { delete p }
T& operator*() const { return *p; }
private:
T* p;
};
// ...
{
memory<int> m0;
*m0 = 3;
std::cout << *m0 << '\n';
}
이 memory
클래스는 거의 정확 : 자동 예외가 그것의 자원을 인수 한 후 약간의 시간을 전파하더라도 출시 자동으로 기본 메모리 공간을 취득합니다. 하지만 다음과 같은 시나리오를 생각해 봅시다 : 우리가 memory
에 대한 전문 복사 의미를 제공하지 않았기 때문에
{
memory<double> m1(3.14);
memory<double> m2(m1); // m2.p == m1.p (do you hear the bomb ticking?)
}
컴파일러는 자신의 복사 생성자를 제공하고 할당을 복사합니다. 이들은 을으로 잘못 처리합니다 : m2 = m1
은 m2.p = m1.p
을 의미하므로 두 개의 포인터가 같은 주소를 가리 킵니다.그것은 잘못된 것입니다 왜냐하면 m2
이 범위를 벗어나서 좋은 책임있는 객체처럼 리소스를 해제하고 m1
이 범위를 벗어나서 리소스를 해제하면 동일한 리소스 m2
이 이미 해제되어 이중 삭제를 완료했기 때문에 잘못되었습니다 - 악명 높은 정의되지 않은 동작 시나리오. 또한 C++에서는 주목할 필요없이 객체의 복사본을 만드는 것이 매우 쉽습니다. 즉, 값으로 매개 변수를 가져 오거나 값으로 매개 변수를 반환하거나 참조로 매개 변수를 가져 오는 함수를 호출 한 다음 해당 함수를 가져 오거나 반환하는 다른 함수를 호출하는 함수입니다. 가치에 의한 매개 변수 ... 그것은 단지 이 일이라고 가정하는 것이 더 쉽습니다.
이 모든 것은 클래스 '존재 이유'가 리소스를 관리 할 때 즉시 복사를 처리해야한다는 것을 알아야한다는 것을 말합니다. 당신은 당신이 무엇을 의미하는지 복사를 결정하는 반면 당신은, 복사를 지원
- 결정해야한다 : 자원의 안전한 공유를 더 공유가 전혀 없다 그래서 기본 자원의 깊은 복사를 수행하거나 copy-on-write에서와 같이 두 가지 방법을 결합 또는 게으른 사본. 어떤 경로를 선택하든 특수 복사 생성자 및 사본 지정 연산자를 제공해야합니다.
- 또는 자원 복사를 지원하지 않으므로 복사 생성자 및 복사 할당 연산자를 비활성화 할 수 있습니다.
나는 자원 관리가 복사를 비활성화하거나 특수 복사 의미를 제공하는 유일한 경우라고 말합니다. 이는 The Rule of Three에 대한 또 다른 관점입니다.
싱글 톤이 하나의 예입니다. –