복사 생성자 비활성화


173

수업이 있습니다.

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

다음과 같은 코드를 비활성화하려면 어떻게 수정해야합니까?

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

다음과 같은 코드 만 허용하십시오.

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

1
Btw, 이것은 상속을위한 조항이있는 싱글 톤입니까 (보호됨)?
R. Martinho Fernandes

코드에서 다른 인스턴스가 생성 될 때마다 GetUniqueInstance ()가 항상 동일한 객체에 대한 참조를 제공한다고 생각합니다.
Pratham Shah

답변:


286

복사 생성자를 비공개로 만들고 구현을 제공하지 않을 수 있습니다.

private:
    SymbolIndexer(const SymbolIndexer&);

또는 C ++ 11에서 명시 적으로 금지하십시오.

SymbolIndexer(const SymbolIndexer&) = delete;

43
delete키워드 와 관련하여 다음을 추가하고 싶습니다. 새 클래스를 디자인 할 때의 현재 습관 delete은 복사 생성자와 할당 연산자 모두입니다. 문맥에 따라 대부분 불필요하며 삭제하면 예기치 않은 동작이 발생하지 않습니다. 복사 ctor가 필요할 수있는 상황이 발생하면 이동 의미론으로 수행 할 수 있는지 판별하십시오. 이것이 바람직하지 않은 경우, 복사 ctor와 할당 연산자 모두에 대한 구현을 제공하십시오. 이것이 좋은 접근법인지 여부는 독자에게 맡길 것입니다.
pauluss86

1
@ pauluss86 나는 당신의 접근 방식을 좋아하지만이 패턴을 따르는 데 소요되는 시간이 오류로 인해 절약되는 시간보다 크다고 생각하기 때문에 완전히 최선을 다하지 않을 것입니다. 확실하지 않을 때마다 복사를 금지합니다.
Tomáš Zato-복권 모니카

@ pauluss86 기본적으로 Rust는 기본적으로 이동합니다 (기본적으로 const-by). 내 의견에 매우 도움이됩니다.
카피 추

33

다중 상속을 신경 쓰지 않는다면 (결국 그렇게 나쁘지는 않습니다) 개인 복사 생성자와 할당 연산자로 간단한 클래스를 작성하고 추가로 서브 클래스 화 할 수 있습니다.

class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};

GCC의 경우 다음과 같은 오류 메시지가 나타납니다.

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private

그래도 이것이 모든 컴파일러에서 작동하는지는 확실하지 않습니다. 거기입니다 관련 질문은 , 아직 응답 없음으로.

UPD :

C ++ 11에서는 NonAssignable다음과 같이 클래스를 작성할 수도 있습니다 .

class NonAssignable {
public:
    NonAssignable(NonAssignable const&) = delete;
    NonAssignable& operator=(NonAssignable const&) = delete;
    NonAssignable() {}
};

delete가 파생 클래스의 기본 건설 한 회원에 더 사용할 수 없도록에서 키워드 방지 회원은 기본적으로 건설되고. GCC에서 할당하려고하면 다음 오류가 발생합니다.

test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:

UPD :

Boost는 이미 같은 목적을 위해 클래스를 가지고 있습니다. 클래스는 boost::noncopyable다음과 같이 호출 되고 사용됩니다.

#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};

프로젝트 정책에서 허용하는 경우 Boost의 솔루션을 고수하는 것이 좋습니다. 자세한 내용은 다른 boost::noncopyable관련 질문 을 참조하십시오.


그럴 필요 없어 NonAssignable(const NonAssignable &other);?
Troyseph

이 질문이 C ++ 11 delete키워드 구문 으로 업데이트되면 더 많은 투표가 될 것이라고 생각 합니다.
Tomáš Zato-복권 모니카

@ TomášZato : 아이디어는 복사 생성자와 할당 연산자를 비공개로 유지하는 것입니다. 당신이 delete그들이라면, 그것은 작동을 멈 춥니 다 (방금 확인했습니다).
firegurafiku

@ TomášZato : 아, 죄송합니다. 테스트 방법이 약간 잘못되었습니다. 삭제도 작동합니다. 잠시 후 답변을 업데이트합니다.
firegurafiku

3
@Troyseph : const Class&그리고 Class const&꽤 동일합니다. 포인터의 경우 심지어 Class const * const유형 이있을 수 있습니다 .
firegurafiku

4

SymbolIndexer( const SymbolIndexer& )비공개로 만드십시오 . 참조에 할당하는 경우 복사하지 않은 것입니다.

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