RAII 란 무엇입니까? 예?


19

항상 RAII라는 용어가 사용될 때 사람들은 실제로 초기화 대신 해체에 대해 이야기하고 있습니다. 나는 그것이 무엇을 의미하는지 기본적인 이해가 있다고 생각하지만 확실하지 않습니다. 또한 : C ++이 유일한 RAII 언어입니까? Java 또는 C # /. NET은 어떻습니까?

답변:


25

Resource Acquisition Is Initialization은 객체가 자체를 완전한 패키지로보아야하며 다른 코드에서 인스턴스에게 "이봐 요, 곧 정리 될 것입니다. 지금 정리하십시오"라고 말하지 않아야한다는 의미입니다. 일반적으로 소멸자에 의미있는 것이 있음을 의미합니다. 또한 예외 처리와 같은 예측하기 어려운 특정 상황에서는 소멸자가 실행되는 것을 알 수 있으므로 리소스를 관리하기 위해 특별히 클래스를 작성합니다.

Windows 커서를 대기 (모래 시계, 작동하지 않는 도넛 등) 커서로 변경하고 작업을 한 다음 다시 변경하는 코드를 작성하려고한다고 가정 해보십시오. 또한 "당신의 일을하라"는 예외를 던질 수 있다고 말하십시오. 이를 수행하는 RAII 방법은 ctor가 커서를 대기하도록 설정 한 클래스, 하나의 "실제"메소드가 원하는대로 수행 한 클래스 및 dtor가 커서를 다시 설정 한 클래스를 작성하는 것입니다. 리소스 (이 경우 커서 상태)는 개체의 범위에 연결됩니다. 리소스를 획득하면 객체를 초기화합니다. 예외가 발생하면 객체가 소멸 될 수 있으므로 리소스를 정리할 수 있습니다.

RAII를 잘 사용하면 필요하지 않습니다 finally. 물론, 그것은 당신이 자바에서는 가질 수없는 결정 론적 파괴에 의존합니다. 를 사용하여 C # 및 VB.NET에서 일종의 결정 론적 파괴를 얻을 수 있습니다 using.


4
나는 이것이 당신이 얻는 것이라고 생각하지만 Java와 C #이 RAII를 지원하지 않는 이유는 가비지 수집기 때문이라고 덧붙일 수 있습니다. C ++에서 로컬 객체는 범위를 벗어나 자마자 파괴됩니다. Java / C #에서는 그렇지 않습니다.
Jason Baker

Jasons의 관점에서 Java와 C #이 적시의 파괴를 보장 할 수없는 이유는 참조주기의 가능성 때문이므로 소멸자를 실행하기위한 안전한 순서를 결정하는 것은 불가능합니다. 참조주기는 C ++에서도 발생할 수 있지만 그 의미는 다릅니다. 프로그래머는 파괴 순서를 결정하고 명시적인 삭제를 수행해야합니다. 그 책임은 종종 일부 상위 클래스 소멸자에 패키지됩니다. 예를 들어 컨테이너 클래스는 포함 된 모든 항목이 소멸되도록합니다. "소유권"이 핵심입니다.
Steve314

1
@Jason 이것이 바로 "결정 론적 파괴"의 의미입니다. C ++ 프로그래머는 소멸자가 언제 실행 될지 알고 있습니다.
Kate Gregory

나는 이것이 오래된 대답이라는 것을 알고 있지만 여전히 다소 혼란 스럽습니다. 방금 용어에 대해 배웠고 일부 정보에 따르면 생성자에서 인수가 발생해야한다고합니다. 그것은 실제로 이해가되지 않으며이 답변은 모순되는 것처럼 보이지만 명확하게 할 수 있습니까?
당 Johansson

1
@PerJohansson 네, 당신은 ctor에서 습득합니다. 그리고 당신은 dtor에서 석방합니다. 나는 두 번째 요점에 집중하고 있었지만 그들은 함께갑니다. ctor가 완료되면 유효한 개체가 있음을 알 수 있습니다. 그리고 무슨 일이 있어도 리소스가 적시에 해제 될 것입니다.
Kate Gregory

4

RAII는 부분적으로 객체가 자체 정리를 담당 할시기를 결정하는 것에 관한 것입니다. 규칙은 생성자가 초기화가 완료 될 때 객체가 책임을지는 규칙입니다. 초기화와 정리의 대칭 인 생성자와 소멸자는 두 사람이 서로 밀접한 관계가 있음을 의미합니다.

RAII의 한 가지 점은 예외 안전을 보장하는 것입니다. 예외가 발생할 때 응용 프로그램이 일관성을 유지합니다. 첫눈에 이것은 사소한 일입니다. 예외로 인해 범위가 종료되면 해당 범위의 지역 변수를 파기해야합니다.

그러나 생성자 내에서 예외 발생이 발생하면 어떻게됩니까?

글쎄, 객체가 완전히 구성되지 않았으므로 안전하게 파괴 할 수 없습니다. 생성자는 예외가 전파되기 전에 필요한 정리가 완료 될 수 있도록 try 블록이 있어야합니다. 객체가 생성 된 범위 밖으로 예외가 전파되면 객체가 처음에 생성되지 않았기 때문에 소멸자 호출이 없습니다.

특히 파괴되는 객체 내부의 멤버 데이터 생성자를 고려하십시오. 그중 하나가 예외를 throw하면 주 생성자 코드가 전혀 실행되지 않지만 해당 생성자의 암시 적 부분을 형성하는 일부 코드가 실행됩니다. 성공적으로 생성 된 멤버는 자동으로 삭제됩니다. 구성되지 않은 구성원 (예외를 던진 구성원 포함)은 그렇지 않습니다.

따라서 기본적으로 RAII는 완전히 생성 된 모든 항목이 특히 예외 처리가있는 경우 적시에 파괴되도록하고, 모든 개체가 완전히 생성되거나 그렇지 않은 것을 보장하는 정책입니다. 안전하게 정리하는 방법을 알 수없는 생성 된 개체). 할당 된 리소스도 해제됩니다. 그리고 많은 작업이 자동화되어 있으므로 프로그래머는 그것에 대해 너무 걱정할 필요가 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.