생성자를 명시 적으로 삭제하는 이유는 무엇입니까?


94

생성자를 언제 / 왜 명시 적으로 삭제해야합니까? 그 이유가 사용을 막기 위함이라고 가정하면, 왜 그렇게하지 private않습니까?

class Foo
{ 
  public: 
    Foo() = delete; 
};

14
그것은 종류의 잘 간다의 = default,조차 클래스를 사용할 수 있으며, 개인적으로보고 선호 삭제 기능을 사용. over Function은 비공개입니다. 전자는 "이것은 사용하기위한 것이 아닙니다."라고 명시 적으로 말합니다. 그것에서 나오는 것이 있다면, 그것을 사용할 수없는 클래스는 실제로 의미 상 차이를 만듭니다.
chris

16
솔직히 사람들이 가까운 투표로 공격적이되기 시작했다고 생각합니다. 이것이 어떻게 건설적이지 않은지 모르겠습니다.
Luchian Grigore

4
@LuchianGrigore : 동의합니다. 나는 왜 커뮤니티가 나 자신이 훨씬 더 경직된 지 궁금해했습니다. 나는 요점을 보지 못한다.
Ed S.

11
C ++ 11을 거의 사용하지 않기 때문에 OP가 인식하는 것보다 더 유익합니다. 생성자에 태그를 지정할 수 있다는 것도 몰랐 습니다 delete. 질문과 Luchian의 대답 모두 쉽게 건설적인 것으로 간주됩니다. C ++ 11의 미세한 요점을 숨겨주지 않는 사람은 곧 두 가지 모두에서 무언가를 얻을 수 있습니다.
WhozCraig

답변:


88

어때 :

//deleted constructor
class Foo
{ 
  public: 
    Foo() = delete;     
  public:
    static void foo();
};

void Foo::foo()
{
   Foo f;    //illegal
}

//private constructor
class Foo
{ 
  private: 
    Foo() {}     
  public:
    static void foo();
};

void Foo::foo()
{
   Foo f;    //legal
}

그들은 기본적으로 다른 것들입니다. private클래스의 멤버 만 해당 메서드를 호출하거나 해당 변수 (또는 친구)에 액세스 할 수 있음을 알려줍니다. 이 경우 static해당 클래스 (또는 다른 멤버) 의 메서드가 클래스 private생성자 를 호출하는 것은 합법적입니다 . 삭제 된 생성자에는 적용되지 않습니다.

여기에서 샘플을 확인 하세요 .


3
Foo (int)를 선언하면 Foo ()를 전혀 선언 할 필요가 없습니다. Foo ()는 생성되지 않으므로 Foo f는 어쨌든 유효하지 않습니다. 따라서 귀하의 예제에는 삭제 된 생성자의 경우가 표시되지 않습니다. - 자신에 대한 참조 ideone.com/mogiIF
표시

1
@mark 나는 요점을 증명하기 위해 2 개의 생성자를 썼다. 모두에게 명확하도록 편집하겠습니다.
Luchian Grigore

1
차이점을 이해합니다. 일반적으로 delete 문의 추가 값과 특히 생성자에 대해 이해하지 못합니다. 결국, 본문없이 개인 기본 생성자를 지정할 수 있습니다. 그런 다음 링크 중에 만 코드가 실패합니다. 음, 삭제가 의도를 더 명시 적으로 전달한다는 것을 알 수 있지만 그게 전부입니다.
마크

11
@mark 예, C ++ 98 방식이 될 것입니다. 그러나 IMHO, 의도를 명확하게 전달하는 것은 실제로 일반적으로 프로그래밍에서 매우 중요한 것입니다. 이 경우 일부 독자는 개인 정의되지 않은 생성자를보고 우발적이라고 가정하고 정의를 추가 할 수 있습니다. -코멘트 시행에 대한 시행). 의도를 더 명확하게함으로써 "정의되지 않은 참조"가 아닌 "명시 적으로 삭제됨"이라는 훨씬 더 나은 오류 메시지를 얻을 수 있습니다.
mpark 2014 년

2
솔직히 이것이 주요 질문에 어떻게 대답하는지 이해하지 못합니다. 게시물의 제목과 OP의 첫 번째 질문에 대한 질문은 다음과 같습니다. 언제 / 왜 생성자를 명시 적으로 삭제하고 싶습니까?
Alexander Bolinsky 2016 년

12

생성자를 명시 적으로 삭제하는 이유는 무엇입니까?

또 다른 이유 : 이니셜 라이저로 클래스를 호출하고 싶을 때
사용 delete합니다. 런타임 검사없이 이것을 달성하는 매우 우아한 방법이라고 생각합니다.

C ++ 컴파일러가이 검사를 수행합니다.

class Foo
{
   public:
       Foo() = delete;
       Foo(int bar) : m_bar(bar) {};
   private:
       int m_bar;
}

매우 단순화 된 이 코드는 다음과 같은 인스턴스화가 없음을 보장합니다.Foo foo;


12
여기서 삭제 된 선언은 필요하지 않습니다. 그것은 자동으로 사용자가 제공 한 생성자 삭제됩니다
마이크 루이를

5
@MikeLui의 주석을 명확히하기 위해 삭제 된 선언은 컴파일러에 필요하지 않습니다. 다른 프로그래머에게 의도 선언하기 위해 이와 같은 코드를 포함해야하는 경우가 많이 있습니다 .
Jeff G

의도를 선언하는 것과 함께 공개 인터페이스에서 삭제 이유를 문서화 할 수있는 분명한 장소를 만들고 추가적으로 컴파일러 오류는 "삭제 된 함수 사용"과 같은 짧은 것입니다. Foo기본 생성자가 아닌 생성자가 여러 개있는 경우 Foo foo;일치하지 못한 모든 암시 적으로 정의되고 보호되는 개인 생성자를 나열하는 훨씬 더 긴 오류가 발생합니다.
sigma

"= delete"키워드가 "기본 생성자 없음"아이디어의 의도를 선언하는 생성자 선언이있는 추가 줄이 기본 생성자가 아닌 것보다 더 나은 방법을 여전히 이해하지 못합니다. 샘플 : 내 코드에서 변수 "a"를 선언하고 싶지 않습니다. "// int a; // 변수 a를 정의 할 필요가 없거나 코드에서이 변수에 대해 아무것도 쓰지 않는 것이 더 낫습니다."
Ezh

2

LLVM의 소스 코드 (예 : AlignOf.h)에서 '삭제됨'으로 선언 된 기본 ctor를 만났습니다. 연결된 클래스 템플릿은 일반적으로 'llvm :: detail'이라는 특수 네임 스페이스에 있습니다. 내가 생각하는 모든 목적은 그들이 그 클래스를 도우미 클래스로만 생각했기 때문이라고 생각합니다. 그들은 그들을 인스턴스화 할 의도가 없었습니다. 컴파일 타임에 실행되는 메타 프로그래밍 트릭이있는 다른 클래스 템플릿의 컨텍스트 내에서만 사용합니다.

예 : 이 AlignmentCalcImpl 클래스 템플릿은 sizeof (.) 연산자의 매개 변수로 AlignOf라는 다른 클래스 템플릿 내에서만 사용됩니다. 이 표현식은 컴파일 타임에 평가 될 수 있습니다. 그리고 템플릿을 인스턴스화 할 필요가 없습니다. 그래서이 의도를 표현하기 위해 기본 ctor delete를 선언하는 것은 어떻습니까?

그러나 그것은 나의 가정 일뿐입니다.

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