소멸자에서 예외 던지기
대부분의 사람들은 소멸자에서 예외를 절대로 버리지 않는다고 말합니다 . 그렇게하면 정의되지 않은 동작이 발생합니다. Stroustrup은 "벡터 소멸자가 모든 요소에 대해 소멸자를 명시 적으로 호출합니다. 이는 요소 소멸자가 던지면 벡터 소멸이 실패 함을 의미합니다. 소멸자에서 발생한 예외를 방지 할 수있는 좋은 방법은 없습니다. 따라서 라이브러리 요소의 소멸자 (부록 E3.2에서) "가 발생하는 경우 보증하지 않습니다 .
이 기사 는 달리 말하는 것으로 보입니다-던지는 소멸자는 다소 괜찮습니다.
그래서 내 질문은 이것입니다-소멸자에서 던지면 정의되지 않은 동작이 발생하면 소멸자 중에 발생하는 오류를 어떻게 처리합니까?
정리 작업 중 오류가 발생하면 무시 하시겠습니까? 스택에서 처리 할 수 있지만 소멸자에서 바로 처리 할 수없는 오류 인 경우 소멸자에서 예외를 발생시키는 것이 합리적이지 않습니까?
분명히 이런 종류의 오류는 드물지만 가능합니다.
소멸자에서 예외를 던지는 것은 위험합니다.
다른 예외가 이미 전파중인 경우 응용 프로그램이 종료됩니다.
#include <iostream>
class Bad
{
public:
// Added the noexcept(false) so the code keeps its original meaning.
// Post C++11 destructors are by default `noexcept(true)` and
// this will (by default) call terminate if an exception is
// escapes the destructor.
//
// But this example is designed to show that terminate is called
// if two exceptions are propagating at the same time.
~Bad() noexcept(false)
{
throw 1;
}
};
class Bad2
{
public:
~Bad2()
{
throw 1;
}
};
int main(int argc, char* argv[])
{
try
{
Bad bad;
}
catch(...)
{
std::cout << "Print This\n";
}
try
{
if (argc > 3)
{
Bad bad; // This destructor will throw an exception that escapes (see above)
throw 2; // But having two exceptions propagating at the
// same time causes terminate to be called.
}
else
{
Bad2 bad; // The exception in this destructor will
// cause terminate to be called.
}
}
catch(...)
{
std::cout << "Never print this\n";
}
}
이것은 기본적으로 다음과 같이 요약됩니다.
위험한 것 (즉, 예외를 던질 수있는 것)은 반드시 공개적인 방법을 통해 수행되어야합니다 (직접적인 것은 아님). 그런 다음 클래스 사용자는 공개 메소드를 사용하고 잠재적 예외를 포착하여 이러한 상황을 처리 할 수 있습니다.
그런 다음 소멸자는 이러한 메소드를 호출하여 오브젝트를 종료하지만 (사용자가 명시 적으로 그렇게하지 않은 경우) 예외가 발생하면 (문제를 해결하려고 시도한 후) 처리됩니다.
따라서 실제로 사용자에게 책임을 전가합니다. 사용자가 예외를 바로 잡을 수있는 위치에 있으면 적절한 함수를 수동으로 호출하고 오류를 처리합니다. 객체의 사용자가 걱정하지 않으면 (객체가 파손될 것이므로) 소멸자는 비즈니스를 처리해야합니다.
예를 들면 :
std :: fstream
close () 메소드는 잠재적으로 예외를 발생시킬 수 있습니다. 파일이 열린 경우 소멸자는 close ()를 호출하지만 예외가 소멸자에서 전파되지 않도록합니다.
따라서 파일 객체의 사용자가 파일 닫기와 관련된 문제에 대해 특별한 처리를하려면 수동으로 close ()를 호출하고 예외를 처리합니다. 반면에 그들은 신경 쓰지 않으면 소멸자는 상황을 처리하도록 남겨 둘 것입니다.
Scott Myers는 그의 저서 "Effective C ++"에서이 주제에 대한 훌륭한 기사를 가지고 있습니다.
편집하다:
"더 효과적인 C ++"
항목 11 :에도 예외가 소멸자를 떠나지 않도록 방지
이 소멸자는 "스택 풀기"의 일부로 호출 될 수 있기 때문에 소멸자를 제외하면 충돌이 발생할 수 있습니다. 스택 해제는 예외가 발생했을 때 발생하는 절차입니다. 이 절차에서는 "시도"이후에 예외로 처리 될 때까지 스택으로 푸시 된 모든 오브젝트가 종료되고 소멸자가 호출됩니다. 그리고이 절차 중에 한 번에 두 개의 예외를 처리 할 수 없기 때문에 또 다른 예외 발생이 허용되지 않으므로 abort () 호출이 발생하고 프로그램이 중단되고 컨트롤이 OS로 돌아갑니다.
특정 사례에 대한 일반적인 조언을 맹목적으로 따르는 대신 여기 를 차별화 해야합니다 .
다음 은 객체 컨테이너의 문제와 컨테이너 내부의 여러 객체에 대한 작업을 무시 합니다. (일부 개체는 컨테이너에 넣기에 적합하지 않기 때문에 부분적으로 무시할 수 있습니다.)
클래스를 두 가지 유형으로 나눌 때 전체 문제를 생각하기가 더 쉬워집니다. 클래스 dtor는 두 가지 다른 책임을 가질 수 있습니다.
- (R) 릴리스 의미론 (일명 메모리를 해제)
- (C) 커밋 의미 (일명 파일을 디스크로 플러시 )
우리가이 질문을 이런 식으로 본다면, 나는 (a) 의미론이 dtor로부터 예외를 일으키지 않아야한다고 주장 할 수 있다고 생각한다. 예를 들어, 오류 점검을 제공합니다 .void
free(void* p);
성공적으로 요구가 다른 종류의있는 dtor에 커밋 않는 그것의 데이터 또는 ( "범위 보호") 데이터베이스 연결을 플러시하는 파일 객체 같은 (C) 의미와 객체 : 우리는 할 수 있습니다 오류에 대해 뭔가를 (에 우리는 실제로 아무 일도 일어나지 않는 것처럼 계속해서는 안됩니다.
RAII 경로를 따르고 d' tors에 (C) 시맨틱이있는 객체를 허용하면 그러한 d' tor가 던질 수있는 이상한 경우도 허용해야한다고 생각합니다. 그런 다음 이러한 오브젝트를 컨테이너에 넣지 말아야 terminate()
하며, 또 다른 예외가 활성화되어있는 동안 commit-dtor가 발생하는 경우 에도 프로그램이 계속 수행 할 수 있습니다 .
오류 처리 (/ 롤백 의미를 커밋) 예외와 관련하여, 하나 좋은 이야기가 안드레이 알렉산드 레스 쿠는 : C에서 오류 처리 ++ / 선언적 제어 흐름 (에서 열린 2014 NDC )
세부 사항에서 그는 Folly 라이브러리 UncaughtExceptionCounter
가 ScopeGuard
툴링을 구현하는 방법을 설명합니다 .
( 다른 사람들 도 비슷한 아이디어를 가지고 있음에 유의해야합니다 .)
강연은 닥터에게 던지는 것에 초점을 맞추지 않지만, 닥터 에게서 던질 때 의 문제를 없애기 위해 오늘날 사용할 수있는 도구를 보여줍니다 .
에서
미래
,가
수
이 들어, 표준 기능이 될
참조
N3614를 ,
그리고 그것에 대해 토론 .
Upd '17 : 이에 대한 C ++ 17 표준 기능이 std::uncaught_exceptions
잘못되었습니다. 나는 cppref 기사를 빨리 인용 할 것이다 :
노트
int
-returninguncaught_exceptions
이 사용되는 예 는 ... ... 먼저 가드 객체를 만들고 생성자에서 포착되지 않은 예외 수를 기록합니다. 출력은 foo ()가 발생하지 않는 한 가드 객체의 소멸자에 의해 수행됩니다 ( 이 경우 소멸자에서 포착되지 않은 예외의 수가 생성자가 관찰 한 것보다 큼 )
소멸자로부터 던지는 것에 대해 스스로에게 묻는 실제 질문은 "발신자가 이것으로 무엇을 할 수 있습니까?" 실제로 소멸자로부터 던질 때 발생하는 위험을 상쇄 할 수있는 예외와 관련하여 유용한 것이 있습니까?
Foo
물체를 파괴 하고 Foo
소멸자가 예외를 던지면 합리적으로 무엇을 할 수 있습니까? 로그하거나 무시할 수 있습니다. 그게 다야. Foo
개체가 이미 없어서 "수정"할 수 없습니다 . 최선의 경우, 예외를 기록하고 아무 일도없는 것처럼 계속합니다 (또는 프로그램을 종료하십시오). 소멸자에서 던져서 정의되지 않은 동작을 유발할 가치가 있습니까?
위험하지만 가독성 / 코드 이해도 관점에서 의미가 없습니다.
당신이 물어봐야 할 것은이 상황입니다
int foo()
{
Object o;
// As foo exits, o's destructor is called
}
예외는 무엇입니까? foo를 호출해야합니까? 아니면 foo가 처리해야합니까? foo 호출자가 foo 내부의 일부 객체를 신경 써야하는 이유는 무엇입니까? 언어가 이것을 이해하도록 정의하는 방법이있을 수 있지만 읽을 수없고 이해하기 어려울 것입니다.
더 중요한 것은 Object의 메모리는 어디에 있습니까? 객체가 소유 한 메모리는 어디에 있습니까? 소멸자가 실패했기 때문에 여전히 할당되어 있습니까? 객체가 스택 공간 에 있었으므로 분명히 상관없이 사라졌습니다.
그런 다음이 경우를 고려하십시오
class Object
{
Object2 obj2;
Object3* obj3;
virtual ~Object()
{
// What should happen when this fails? How would I actually destroy this?
delete obj3;
// obj 2 fails to destruct when it goes out of scope, now what!?!?
// should the exception propogate?
}
};
obj3 삭제가 실패하면 실제로 실패하지 않는 방법으로 삭제하는 방법은 무엇입니까? 내 기억이 엉망이야!
이제 첫 번째 코드 스 니펫에서 Object3가 힙에 있고 스택에 있기 때문에 자동으로 사라지는 것을 고려하십시오. Object3에 대한 포인터가 사라 졌으므로 일종의 SOL입니다. 메모리 누수가 있습니다.
이제 일을하는 안전한 방법은 다음과 같습니다.
class Socket
{
virtual ~Socket()
{
try
{
Close();
}
catch (...)
{
// Why did close fail? make sure it *really* does close here
}
}
};
이 FAQ 도 참조하십시오
C ++ 용 ISO 초안에서 (ISO / IEC JTC 1 / SC 22 N 4411)
따라서 소멸자는 일반적으로 예외를 잡아서 소멸자로부터 전파되지 않도록해야합니다.
3 try 블록에서 throw 식까지의 경로에 구성된 자동 객체에 대해 소멸자를 호출하는 프로세스를 "스택 풀기"라고합니다. [참고 : 스택 해제 중 호출 된 소멸자가 예외와 함께 종료되면 std :: terminate가 (15.5.1)이라고합니다. 따라서 소멸자는 일반적으로 예외를 잡아서 소멸자로부터 전파되지 않도록해야합니다. — 끝 참고]
소멸자는 다른 소멸자 내에서 실행 중일 수 있습니다. 즉시 호출자가 잡지 않은 예외를 처리하면 여러 오브젝트가 일관성이없는 상태로 남아있어 더 많은 문제점이 발생하여 정리 조작에서 오류를 무시할 수 있습니다.
다른 사람들은 왜 소멸자를 던지는 것이 끔찍한 지 설명했습니다. 어떻게 할 수 있습니까? 실패 할 수있는 작업을 수행하는 경우 정리를 수행하고 임의의 예외가 발생할 수있는 별도의 공용 메서드를 만듭니다. 대부분의 경우 사용자는이를 무시합니다. 정리 성공 / 실패를 모니터링하려는 경우 명시 적 정리 루틴을 호출하면됩니다.
예를 들면 다음과 같습니다.
class TempFile {
public:
TempFile(); // throws if the file couldn't be created
~TempFile() throw(); // does nothing if close() was already called; never throws
void close(); // throws if the file couldn't be deleted (e.g. file is open by another process)
// the rest of the class omitted...
};
훌륭하고 포괄적이며 정확한 주요 답변 외에도 "소멸자에서 예외를 던지는 것은 그렇게 나쁘지 않습니다"라는 기사에 대해 언급하고 싶습니다.
이 기사는 "예외를 던지는 대안은 무엇입니까?"라는 문구를 사용하고 각 대안에 대한 몇 가지 문제점을 나열합니다. 그렇게하면 문제가없는 대안을 찾을 수 없으므로 예외를 계속 발생시켜야한다는 결론을 내립니다.
문제는 대안들과 함께 나열된 문제들 중 어느 것이 "프로그램의 정의되지 않은 행동"이라는 예외 행동만큼 나쁘지 않다는 것입니다. 저자의 반대 의견 중 일부는 "미학적으로 추악한"및 "나쁜 스타일 격려"를 포함합니다. 이제 어느 쪽을 원하십니까? 스타일이 나쁜 프로그램이나 정의되지 않은 행동을 보이는 프로그램?
나는 소멸자에 던지는 "스코프 가드"패턴이 많은 상황, 특히 단위 테스트에 유용하다고 생각하는 그룹에 속합니다. 그러나 C ++ 11에서는 std::terminate
소멸자가 내재적으로 주석 처리되어 있기 때문에 소멸자 를 던지면 호출이 발생합니다 noexcept
.
Andrzej Krzemieński는 다음을 던지는 소멸자 주제에 대한 훌륭한 게시물을 가지고 있습니다.
그는 C ++ 11 noexcept
에 소멸자 의 기본값을 재정의하는 메커니즘이 있다고 지적했다 .
C ++ 11에서 소멸자는 암시 적으로로 지정됩니다
noexcept
. 사양을 추가하지 않고 다음과 같이 소멸자를 정의하더라도 :class MyType { public: ~MyType() { throw Exception(); } // ... };
컴파일러는 여전히 보이지 않게
noexcept
소멸자 에 사양 을 추가 합니다. 그리고 이것은std::terminate
이중 예외 상황이 없더라도 소멸자가 예외를 던지는 순간에 호출됩니다. 소멸자가 던질 수 있도록 결정했다면이를 명시 적으로 지정해야합니다. 세 가지 옵션이 있습니다.
- 소멸자를 명시 적으로
noexcept(false)
,- 이미 소멸자를로 지정하는 다른 클래스에서 클래스를 상속하십시오
noexcept(false)
.- 이미 소멸자를로 지정하는 정적이 아닌 데이터 멤버를 클래스에 넣습니다
noexcept(false)
.
마지막으로 소멸자를 던지기로 결정한 경우 항상 이중 예외의 위험에 대해 알고 있어야합니다 (예외로 인해 스택이 풀리는 동안 발생). 이로 인해 전화 std::terminate
가 걸리며 원하는 것은 거의 없습니다. 이 동작을 피하려면을 사용하여 새 예외를 던지기 전에 이미 예외가 있는지 확인하면됩니다 std::uncaught_exception()
.
Q : 내 질문은 이것입니다-소멸자에서 던질 때 정의되지 않은 동작이 발생하면 소멸자 중에 발생하는 오류를 어떻게 처리합니까?
A : 몇 가지 옵션이 있습니다.
다른 곳에서 무슨 일이 일어나 든 관계없이 예외가 소멸자에게 흘러 나오게하십시오. 그리고 그렇게 할 때 std :: terminate가 뒤따를 수 있음을 인식하십시오.
소멸자에게 예외가 흘러 가지 않도록하십시오. 가능한 경우 큰 빨간색 나쁜 텍스트를 로그에 쓸 수 있습니다.
내 fave :
std::uncaught_exception
false를 반환하면 예외가 발생합니다. true를 반환하면 로깅 방식으로 돌아갑니다.
그러나 d' tors에 던지는 것이 좋은가요?
나는 위의 대부분이 소멸자에서 가능한 한 피하는 것이 가장 좋습니다. 그러나 때때로 당신은 그것이 일어날 수 있다는 것을 받아들이고 잘 처리하는 것이 가장 좋습니다. 위의 3을 선택하겠습니다.
실제로 소멸자에게 던질 좋은 아이디어 가있는 몇 가지 이상한 경우가 있습니다. "확인해야합니다"오류 코드와 같습니다. 이것은 함수에서 반환되는 값 형식입니다. 호출자가 포함 된 오류 코드를 읽거나 확인하면 반환 된 값이 자동으로 소멸됩니다. 그러나 반환 값이 범위를 벗어날 때까지 반환 된 오류 코드를 읽지 않으면 소멸자에서 예외가 발생 합니다.
나는 현재 클래스가 소멸자로부터 예외를 적극적으로 던져서는 안되고 대신 실패 할 수있는 작업을 수행하기 위해 공개 "닫기"방법을 제공해야한다는 정책 (많은 사람들이 말하고 있음)을 따르고 있습니다 ...
... 그러나 벡터와 같은 컨테이너 유형 클래스의 소멸자는 포함 된 클래스에서 발생하는 예외를 마스킹해서는 안된다고 생각합니다. 이 경우 실제로 재귀 적으로 호출되는 "free / close"메서드를 사용합니다. 예, 재귀 적으로 말했습니다. 이 광기에 대한 방법이 있습니다. 예외 전파는 스택에 의존합니다. 단일 예외가 발생하면 나머지 소멸자가 여전히 실행되고 루틴이 리턴되면 보류중인 예외가 전파됩니다. 여러 예외가 발생하면 (컴파일러에 따라) 첫 번째 예외가 전파되거나 프로그램이 종료됩니다. 재귀로 인해 스택에 오버플로가 발생하는 예외가 너무 많이 발생하면 심각한 문제가 발생하여 누군가가 그것에 대해 알게 될 것입니다. 몸소,
요점은 컨테이너가 중립을 유지하고 소멸자로부터 예외를 던지는 것과 관련하여 컨테이너가 동작하는지 오작동 하는지를 결정하는 것은 포함 된 클래스에 달려 있다는 것입니다.
Martin Ba (위)는 RELEASE와 COMMIT 논리에 대해 다르게 설계했습니다.
출시 :
오류를 먹어야합니다. 메모리를 비우거나 연결을 끊는 등의 작업을 수행하고 있습니다. 시스템의 어느 누구도 이러한 정보를 다시 볼 수 없으며 OS에 리소스를 넘겨 줄 수 없습니다. 여기에 실제 오류 처리가 필요한 것 같으면 객체 모델의 디자인 결함으로 인한 것일 수 있습니다.
커밋 :
여기서 std :: lock_guard와 같은 것들이 뮤텍스를 제공하는 것과 같은 종류의 RAII 래퍼 객체를 원합니다. 그것들을 사용하면 커밋 로직을 dtor AT ALL에 넣지 않습니다. 전용 API가 있고, RAIR이 해당 API를 RAIR 커밋하고 오류를 처리 할 래퍼 객체를 래퍼합니다. 소멸자에서 예외를 잘 잡을 수 있다는 것을 기억하십시오. 그들에게 치명적인 발행. 또한 다른 래퍼 (예 : std :: unique_lock vs. std :: lock_guard)를 작성하여 정책 및 다른 오류 처리를 구현할 수 있으며, 커밋 논리를 호출하는 것을 잊지 않아야합니다. 그것을 1 위의 dtor에 넣는 것에 대한 적절한 정당성.
알람 이벤트를 설정하십시오. 일반적으로 경보 이벤트는 물체를 청소하는 동안 고장을 알리는 더 나은 형태입니다.
예외를 던지는 것이 객체 생성이 성공했음을 나타내는 유용한 방법 일 수있는 생성자와는 달리, 소멸자에서 예외를 발생시키지 않아야합니다.
스택 해제 프로세스 중에 소멸자에서 예외가 발생하면 문제가 발생합니다. 이 경우 컴파일러는 스택 해제 프로세스를 계속할지 아니면 새 예외를 처리할지 여부를 모르는 상황에 처하게됩니다. 결과적으로 프로그램이 즉시 종료됩니다.
결과적으로 최선의 조치는 소멸자에서 예외를 사용하지 않는 것입니다. 대신 로그 파일에 메시지를 작성하십시오.
그래서 내 질문은 이것입니다-소멸자에서 던지면 정의되지 않은 동작이 발생하면 소멸자 중에 발생하는 오류를 어떻게 처리합니까?
주요 문제는 이것입니다 : 당신은 실패 할 수 없습니다 . 결국 실패하지 못한다는 것은 무엇을 의미합니까? 트랜잭션을 데이터베이스에 커밋하는 데 실패하고 실패 (롤백 실패)하면 데이터 무결성은 어떻게됩니까?
소멸자는 일반적인 경로와 예외적 인 (실패한) 경로 모두에 대해 호출되므로 스스로 실패 할 수 없거나 "실패하지 못합니다".
이것은 개념적으로 어려운 문제이지만 종종 해결책은 실패가 실패하지 않도록하는 방법을 찾는 것입니다. 예를 들어 데이터베이스는 외부 데이터 구조 또는 파일을 커밋하기 전에 변경 사항을 쓸 수 있습니다. 트랜잭션이 실패하면 파일 / 데이터 구조를 버릴 수 있습니다. 그러면 외부 구조 / 파일에서 변경 사항을 커밋해도 실패하지 않는 원자 트랜잭션을 보장 할 수 있습니다.
실용적 해결책은 실패에 실패하는 것을 불가능하게 만드는 것이 거의 불가능할 수 있기 때문에 실패에 실패 할 가능성을 천문학적으로 불가능하게 만드는 것입니다.
나에게 가장 적합한 해결책은 정리 논리가 실패하지 않는 방식으로 비 정리 논리를 작성하는 것입니다. 예를 들어, 기존의 데이터 구조를 정리하기 위해 새로운 데이터 구조를 만들고 싶은 경우, 더 이상 소멸자 내부에서 생성 할 필요가 없도록 해당 보조 구조를 미리 만들려고 할 수 있습니다.
이것은 분명히 말한 것보다 훨씬 쉽지만, 그것에 관해 내가 보는 유일한 방법입니다. 때로는 예외적 인 경로와는 거리가 먼 일반 실행 경로에 대해 별도의 소멸자 논리를 작성할 수 있어야한다고 생각합니다. 예외적 인 경로를 예외가 아닌 경로와 구별 할 수 있다면이를 필요로하지 않을 것입니다).
여전히 궁극적 인 문제는 우리가 실패 할 수 없다는 것입니다. 모든 경우에 완벽하게 해결하는 것은 어려운 개념 설계 문제입니다. 복잡한 물체가 서로 상호 작용하는 복잡한 제어 구조로 너무 복잡하게 싸이 지 않고 약간 더 큰 방식으로 디자인을 모델링 (예 : 전체 입자를 파괴하는 소멸자가있는 입자 시스템)하면 더 쉬워집니다 파티클마다 별도의 사소한 소멸자가 아닌 시스템). 이런 종류의 거친 수준에서 디자인을 모델링 할 때 다루기 어려운 소멸자가 적고 소멸자가 실패하지 않도록 메모리 / 프로세싱 오버 헤드가 필요한 경우가 종종 있습니다.
그리고 자연스럽게 가장 쉬운 해결책 중 하나는 소멸자를 덜 자주 사용하는 것입니다. 위의 입자 예에서, 아마도 입자를 파괴 / 제거 할 때 어떤 이유로 든 실패 할 수있는 몇 가지 작업을 수행해야합니다. 이 경우 예외 경로에서 실행될 수있는 입자의 dtor를 통해 이러한 논리를 호출하는 대신, 입자를 제거 할 때 입자 시스템에서 모두 수행 할 수 있습니다 . 예외가 아닌 경로에서 입자 제거가 항상 수행 될 수 있습니다. 시스템이 파괴되면 모든 파티클을 퍼지 할 수 있고 실패 할 수있는 개별 파티클 제거 로직을 방해하지 않는 반면 실패 할 수있는 로직은 하나 이상의 파티클을 제거 할 때 파티클 시스템의 정상적인 실행 중에 만 실행됩니다.
사소한 소멸자가 아닌 많은 작은 물체를 다루지 않으면 자라는 솔루션과 같은 솔루션이 종종 있습니다. 예외 안전이 거의 불가능 해 보이는 혼란에 빠질 수있는 곳은 모두 사소한 dtor가있는 아주 작은 물체에 얽힌 경우입니다.
nothrow / noexcept가 실제로 그것을 지정하는 것 (기본 클래스의 noexcept 사양을 상속 해야하는 가상 함수 포함)이 던질 수있는 것을 호출하려고 시도하면 실제로 컴파일러 오류로 변환되면 많은 도움이 될 것입니다. 이렇게하면 실수로 던질 수있는 소멸자를 실제로 작성하면 컴파일 타임 에이 모든 것을 잡을 수 있습니다.
참고 URL : https://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor
'Programing' 카테고리의 다른 글
WebKit이란 무엇이며 CSS와 어떤 관련이 있습니까? (0) | 2020.04.08 |
---|---|
C ++에서 make_shared와 normal shared_ptr의 차이점 (0) | 2020.04.08 |
스칼라의 방법과 기능의 차이 (0) | 2020.04.08 |
CSS에서 @media screen과 (최대 너비 : 1024px)의 의미는 무엇입니까? (0) | 2020.04.08 |
느낌표는 하스켈 선언에서 무엇을 의미합니까? (0) | 2020.04.08 |