디폴트소멸자는 아무런 동작을 하지않나요?

skazkchdrj42의 이미지

delete말고
소멸자만 호출했을때 별 다른 동작을 안해서요..
객체도 그대로 살아있고요
아무런 동작이 없는건가요?

익명 사용자의 이미지

1. 멤버 변수가 있다면 멤버 변수를 소멸시킵니다.

2. 상속받은 클래스가 있다면 그 클래스의 소멸자가 불립니다.

3. 그대로 살아 있는지 어떻게 아시나요?
살아 있는 것처럼 보여도 소멸자가 죄다 불린 상태이기 때문에 (정상적으로 짜인 클래스라면) 속 빈 강정 상태가 됩니다.

정상적으로 안 짜인 클래스라면 이런 이상한 짓도 할 수 있습니다:

#include <iostream>
 
class Base{ public: ~Base(){ std::cout << "Base class is destructing...\n"; } };
class Member{ public: ~Member(){ std::cout << "Member class is destructing...\n"; } };
 
class Obj: public Base { Member member; };
 
int main(){
	char dummy;
	reinterpret_cast<Obj *>(&dummy)->~Obj();
 
	return 0;
}

클래스 Obj의 인스턴스는 프로그램 전체에 걸쳐 단 하나도 생성되지 않지만
그렇다 해도 아무래도 상관없는 코드이기 때문에 컴파일해서 실행시키면 동작은 합니다.

물론 이런 코드 짜면 안 됩니다 ㅎㅎ.

skazkchdrj42의 이미지

class Test
{
public:
	Test()
	{
	}
	~Test()
	{
	}
 
	int Member = 9999;
};
 
 
int main()
{
	Test* t = new Test();
	t->~Test();
 
	int Num = t->Member;
}

소멸자만 호출하면
Num에 9999가 들어와요

	delete t;
 
	int Num = t->Member;

반면에 delete하고 보면 Num에 쓰레기값이 들어가요
이런거 보면 멤버소멸은 delete가 해주고
기본소멸자 자체로서는 아무런 동작이 없는거아닌가요?
익명 사용자의 이미지

위 답변을 뒤집으면,

1. 소멸시킬 멤버가 없고 2. 상속받은 클래스도 없다면 기본 소멸자는 할 일이 없습니다.

올려주신 코드의 Test가 딱 그런 경우죠.
필드가 하나 (Member) 있긴 한데 정수값 달랑 하나 들고 있는 int 타입이잖아요.
9999 대신 다른 값(쓰레기값?)이 저장되어 있으면 죽은 건가요?

delete 이후에 t->Member의 값이 변하는 이유는, delete가 동적 할당된 메모리를 회수하기 때문입니다. 이건 구현 의존적입니다.

동적 할당 메모리를 관리하기 위한 자료구조 때문인 것일 수도 있지만, 그보다는 아마 use-after-free 버그를 쉽게 확인하기 위한 디버그 기능일 가능성이 높을 거에요.

사실 제시된 코드가 바로 use-after-free를 일으키는 예시인데, t->Member 값이 바뀐 덕분에 그 사실을 바로 알아챌 수 있죠.

eagle76fish의 이미지

소멸자가 호출되는 경우 몇 가지 상황이 있습니다.

실행되는 코드가 객체가 선언된 유효범위를 벗어날 때
동적 할당된 객체에 대해 그 앞에서 delete를 언급할 때

동적할당된 객체가 아니라면, 첫 번째의 경우에 해당되 소멸자가 호출되면서, 자동으로 객체가 소멸됩니다. 두 번째 동적할당된 객체는 반드시 delete를 앞에 언급해야 하고요.
비록 소멸자가 호출된다 하더라도 객체 내부의 동적할당된 자원은 누수되지 않도록 delete로 해제해줘야 하고요.
멤버소멸이라는 개념어는 기본서에 언급된 바 없습니다. 어떤 의밀 언급하셨는지 모르나, 객체 내부의 자원(즉 동적할당된 멤버변수들)을 해제한다는 의미에서 멤버소멸이라는 단어를 선택하신 거면, 멤버소멸은 소멸자가 이행하는 것입니다. delete는 동적할당된 공간을 접으면서 소멸자를 호출하는고로 동적할당 공간정리와 멤버소멸 두 작업을 이행하게끔 하는 것이고요.

앞에서 질문자께서 작성하신 글처럼 직접 소멸자를 호출해서 객체를 소멸하는 경우는 제가 본 바가 없습니다. 가급적 동적할당된 객체는 delete를 사용해서 소멸시키는 것이 좋겠습니다.

익명 사용자의 이미지

eagle76fish wrote:
직접 소멸자를 호출해서 객체를 소멸하는 경우는 제가 본 바가 없습니다.

흔한 경우는 아닙니다만 그렇게 해야만 하는 경우가 없지는 않습니다.

객체를 위한 메모리의 할당(해제)과 객체의 생성(소멸)을 분리해야 하는 경우가 있거든요.

대표적으로
1. 메모리는 미리 잡아놓아야 하지만 아직 객체를 생성할 수는 없는 경우 (e.g., std::vector)
2. 객체를 위한 메모리를 뭔가 다른 방식으로 할당받아야 하는 경우

그럴 때는 1. placement new를 통해 객체를 생성하고, 소멸자를 직접 호출해서 객체를 소멸시켜야 합니다.

awidesky의 이미지

https://en.cppreference.com/w/cpp/language/destructor

If an implicitly-declared destructor is not deleted, it is implicitly defined (that is, a function body is generated and compiled) by the compiler when it is odr-used. This implicitly-defined destructor has an empty body.

기본 소멸자는 아무 동작도 하지 않습니다.
그리고 delete한 메모리를 접근하는 건 UB입니다..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.