class my_class
{
...
my_class(my_class const &) = delete;
...
};
= delete
그 맥락에서 무엇을 의미합니까?
다른 "수정 자"( = 0
및 이외 = delete
)가 있습니까?
#define
0으로 평가 된 다음 숨겨진 함수 또는 무언가를 선언 한 la Qt 라고 생각했습니다 .
class my_class
{
...
my_class(my_class const &) = delete;
...
};
= delete
그 맥락에서 무엇을 의미합니까?
다른 "수정 자"( = 0
및 이외 = delete
)가 있습니까?
#define
0으로 평가 된 다음 숨겨진 함수 또는 무언가를 선언 한 la Qt 라고 생각했습니다 .
답변:
함수 삭제는 C ++ 11 기능입니다 .
"복사 금지"의 일반적인 관용구를 이제 직접 표현할 수 있습니다.
class X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };
[...]
"삭제"메커니즘은 모든 기능에 사용할 수 있습니다. 예를 들어 다음과 같이 원하지 않는 변환을 제거 할 수 있습니다.
struct Z { // ... Z(long long); // can initialize with an long long Z(long) = delete; // but not anything less };
=delete
는 메소드를 볼 수있는 컨텍스트 private
(예 : 클래스와 친구 내) 에서도 메소드에 액세스 할 수 없게 합니다. 코드를 읽을 때 불확실성을 제거합니다. @Prasoon, 두 번째 예는 여전히 생성자를 삭제하는 것 operator long ()
입니다. 예를 들어 삭제 된 것을 보는 것이 좋습니다 .
= delete
더 나은 사용하는 것보다 private
일반적으로이 때문에 또는 다른 유사한 메커니즘 원하는 금지 된 기능이 눈에 띄게 선언 및 오버로드 확인 등을 위해 고려되어야하는 것이 가능한 한 빨리 실패하고 사용자에게 명확한 오류를 제공 할 수 있도록. 선언을 "숨김"과 관련된 솔루션은이 효과를 줄입니다.
= 0
함수가 순수 가상이고이 클래스에서 객체를 인스턴스화 할 수 없음을 의미합니다. 그것에서 파생 되어이 방법을 구현해야합니다= delete
컴파일러가 생성자를 생성하지 않음을 의미합니다. AFAIK 이것은 복사 생성자 및 할당 연산자에서만 허용됩니다. 그러나 나는 다가오는 표준에 너무 좋지 않다.=delete
구문 의 다른 용도가 있습니다. 예를 들어, 호출로 발생할 수있는 암시 적 변환을 명시 적으로 허용하지 않을 때 사용할 수 있습니다. 이를 위해 오버로드 된 기능을 삭제하십시오. 자세한 정보는 C ++ 0x의 Wikipedia 페이지를 참조하십시오.
= delete
이 완전히 정확하지 않습니다. = delete
모든 함수에 사용할 수 있으며,이 경우 명시 적으로 삭제 된 것으로 표시되고 사용하면 컴파일러 오류가 발생합니다. 특수 멤버 함수의 경우 이는 특히 컴파일러에서 생성하지 않지만 = delete
실제로는 삭제되지 않은 결과 일뿐 입니다.
The C ++ Programming Language [4th Edition]-Bjarne Stroustrup의 발췌문은 다음을 사용 하는 실제 목적 에 대해 이야기합니다 =delete
.
3.3.4 작동 억제
계층 구조에서 클래스에 대한 기본 복사 또는 이동을 사용하는 것은 일반적으로 재난입니다 . 기본에 대한 포인터 만 제공하면 파생 클래스의 멤버를 모를 뿐이므로 복사 방법을 알 수 없습니다 . 따라서 가장 좋은 방법은 일반적으로 기본 복사 및 이동 작업을 삭제하는 것, 즉이 두 작업의 기본 정의를 제거하는 것입니다.
class Shape { public: Shape(const Shape&) =delete; // no copy operations Shape& operator=(const Shape&) =delete; Shape(Shape&&) =delete; // no move operations Shape& operator=(Shape&&) =delete; ˜Shape(); // ... };
이제 셰이프를 복사하려는 시도가 컴파일러에 의해 포착됩니다.
=delete
메커니즘은 어떤 동작을 억제하기 위해 사용될 수있는, 즉 일반적이며
다른 "수정 자"(
= 0
및 이외= delete
)가 있습니까?
다른 사람이이 질문에 대답하지 않은 것 같기 때문에 나는 또한 언급해야한다 =default
.
내가 작업 한 코딩 표준에는 대부분의 클래스 선언에 대해 다음과 같은 내용이 있습니다.
// coding standard: disallow when not used
T(void) = delete; // default ctor (1)
~T(void) = delete; // default dtor (2)
T(const T&) = delete; // copy ctor (3)
T(const T&&) = delete; // move ctor (4)
T& operator= (const T&) = delete; // copy assignment (5)
T& operator= (const T&&) = delete; // move assignment (6)
이 6 개 중 하나를 사용하면 해당 라인을 주석 처리하면됩니다.
예 : FizzBus 클래스는 dtor 만 필요하므로 다른 5 개는 사용하지 마십시오.
// coding standard: disallow when not used
FizzBuzz(void) = delete; // default ctor (1)
// ~FizzBuzz(void); // dtor (2)
FizzBuzz(const FizzBuzz&) = delete; // copy ctor (3)
FizzBuzz& operator= (const FizzBuzz&) = delete; // copy assig (4)
FizzBuzz(const FizzBuzz&&) = delete; // move ctor (5)
FizzBuzz& operator= (const FizzBuzz&&) = delete; // move assign (6)
여기서는 1 개만 주석 처리하고 다른 곳에 구현을 설치하십시오 (아마도 코딩 표준이 제안하는 위치). 나머지 5 개 중 6 개는 삭제가 허용되지 않습니다.
'= delete'를 사용하여 다른 크기 값의 암시 적 승격을 허용하지 않을 수도 있습니다 ... 예
// disallow implicit promotions
template <class T> operator T(void) = delete;
template <class T> Vuint64& operator= (const T) = delete;
template <class T> Vuint64& operator|= (const T) = delete;
template <class T> Vuint64& operator&= (const T) = delete;
새로운 C ++ 0x 표준. N3242 작업 초안 의 섹션 8.4.3을 참조하십시오
(기존 답변에 대한 부록)
... 그리고 삭제 된 함수는 함수의 첫 번째 선언이어야합니다 (함수 템플릿의 명시 적 전문화를 삭제하는 것을 제외하고-삭제는 전문화의 첫 번째 선언에 있어야 함). 함수를 선언하고 나중에 삭제할 수 없음을 의미합니다. 정의에 따라 번역 단위에 국한됩니다.
삭제 된 함수는 암시 적으로 인라인입니다. ( 참고 : 1- 정의 규칙 ( [basic.def.odr] )은 삭제 된 정의에 적용됩니다. — 끝 주 ] 함수의 삭제 된 정의는 함수의 첫 번째 선언이거나 함수 템플릿의 명시 적 전문화 여야합니다. , 해당 전문화의 첫 번째 선언 [예 :
struct sometype { sometype(); }; sometype::sometype() = delete; // ill-formed; not first declaration
— 최종 예 )
일반적 으로 전문화는 과부하 해결의 첫 번째 단계에 참여하지 않기 때문에 기능 템플릿 특수화를 피하는 것이지만 유용한 컨텍스트가 있습니다. 예를 들어, 정의가없는 오버로드되지 않은 기본 함수 템플릿을 사용하여 변환과 일치하는 오버로드로 암시 적으로 변환되지 않는 모든 유형과 일치하는 경우 즉, 정의되지 않은 오버로드되지 않은 기본 함수 템플릿의 명시적인 특수화에서 정확한 형식 일치 만 구현하여 여러 개의 암시 적 변환 일치를 암시 적으로 제거합니다.
C ++ 11의 삭제 된 함수 개념 이전에는 기본 함수 템플릿의 정의를 생략하여이를 수행 할 수 있었지만 기본 함수 템플릿 작성자의 의미 론적 의도가 전혀 없었던 정의되지 않은 참조 오류가 발생했습니다 (의도적으로 생략되었습니다) ?). 대신 기본 함수 템플릿을 명시 적으로 삭제하면 적절한 명시 적 전문화를 찾을 수없는 경우의 오류 메시지가 훨씬 더 좋아지고 기본 함수 템플릿 정의의 생략 / 삭제가 의도적 인 것임을 나타냅니다.
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t);
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
//use_only_explicit_specializations(str); // undefined reference to `void use_only_explicit_specializations< ...
}
그러나 위의 1 차 함수 템플리트에 대한 정의를 생략하고 명시적인 특수화와 일치하지 않는 경우 불명확 한 참조 오류가 발생하는 대신 1 차 템플리트 정의를 삭제할 수 있습니다.
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t) = delete;
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
use_only_explicit_specializations(str);
/* error: call to deleted function 'use_only_explicit_specializations'
note: candidate function [with T = std::__1::basic_string<char>] has
been explicitly deleted
void use_only_explicit_specializations(T t) = delete; */
}
삭제 의도도 명확하게 보이는 더 읽기 쉬운 오류 메시지를 생성합니다 ( 정의되지 않은 참조 오류로 인해 개발자가이를 생각하지 못한 실수로 생각할 수 있음).
왜이 기술을 사용하고 싶습니까? 또, 명시 적 특수화는 것이 유용 할 수 암묵적으로 암시 적 변환을 제거합니다.
#include <cstdint>
#include <iostream>
void warning_at_best(int8_t num) {
std::cout << "I better use -Werror and -pedantic... " << +num << "\n";
}
template< typename T >
void only_for_signed(T t) = delete;
template<>
void only_for_signed<int8_t>(int8_t t) {
std::cout << "UB safe! 1 byte, " << +t << "\n";
}
template<>
void only_for_signed<int16_t>(int16_t t) {
std::cout << "UB safe! 2 bytes, " << +t << "\n";
}
int main()
{
const int8_t a = 42;
const uint8_t b = 255U;
const int16_t c = 255;
const float d = 200.F;
warning_at_best(a); // 42
warning_at_best(b); // implementation-defined behaviour, no diagnostic required
warning_at_best(c); // narrowing, -Wconstant-conversion warning
warning_at_best(d); // undefined behaviour!
only_for_signed(a);
only_for_signed(c);
//only_for_signed(b);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = unsigned char]
has been explicitly deleted
void only_for_signed(T t) = delete; */
//only_for_signed(d);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = float]
has been explicitly deleted
void only_for_signed(T t) = delete; */
}