`new int;`의`new`는 연산자로 간주됩니까?


84

new int;in과 같은 표현식 int * x = new int;새로운 표현식 입니다. "new operator"라는 용어는 "new expression"과 같은 의미로 사용되는 것 같습니다. 예를 들어이 질문 에서 'new operator'와 'operator new'의 차이점은 무엇입니까?

키워드가 new새 표현식에 사용 된 가 연산자 습니까? 그 이유는 무엇?

그렇지 않은 경우 새 표현식 "새 연산자"를 호출하는 또 다른 이유가 있습니까?

운영자를 구성하는 것에 대한 권위있는 정의를 찾는 데 문제가 있습니다.

나는 이미 객체에 메모리를 할당하는 연산자 new 와 결국 operator new.


4
@Rogue-사물은 여기 newsizeof같습니다. 그리고 저는 대부분의 C ++ 커뮤니티가 sizeof연산자로 생각한다고 생각 합니다. 표준은 sizeof그 효과를 설명 할 때 " 연산자"를 언급하기도합니다.
StoryTeller-Unslander Monica

2
@ StoryTeller-UnslanderMonica는 두 번째 댓글 (현재 답변으로 이동)에서 계속해서을 사용 sizeof하여 표현식의 연산자라고 말하고 싶습니다 sizeof(<type>). 그리고 +단항 표현식에 대한 연산자입니다 <type> <op> <type>. 그것은 적어도 내 테이크 아웃 / 해석입니다. 자유롭게 수정하십시오.
Rogue

2
@Rogue-그렇습니다. 그렇기 때문에 하나를 연산자로 참조하고 다른 하나를 참조하지 않을 때 규범 적 텍스트가 다소 임의적이라고 주장합니다.
StoryTeller-Unslander Monica 2010 년

1
허용되는 답변에 대한 추가 참고 사항 : new연산자 인지 아닌지에 관계없이 식과 연산자 사이에는 차이가 있습니다. 예를 들어, new int무엇인가를 평가하는 표현입니다. new가 연산자로 간주 되면 의 "새로운"부분 만 new int연산자입니다 (즉, 자체적으로 분리됨). 개념적으로 연산자는 다른 것에 작용하는 것입니다.
Filip Milovanović

답변:


140

newin new int은 연산자로 간주되지 않습니다. 또한으로 간주되지 않습니다 하지 연산자.

C ++ 표준은 '연산자'를 구성하는 것에 대해 정말 모호하고 일관성이 없습니다. 연산자를 나열 할 때 (어휘 처리 및 전처리 중에 정의 된대로) "구두 자"(와 같은 것 () 와 함께 나열 하지만 일반적으로 구두점에 대한 규칙은 제공하지 않습니다. new키워드와 연산자로 나열 됩니다. sizeof키워드 세트 에는 나열 되지만 연산자 세트 에는 나열 되지 않지만 나중에 연산자로 참조됩니다.

여기서 중요한 점은 C ++ 표준위원회가 어휘 세계를 "운영자"와 "비 운영자"로 분리하는 데 지나치게 관심이 없다는 것입니다. 그럴 필요가 없기 때문입니다. 모든 연산자 또는 모든 비 연산자에 적용되는 문법 규칙은 없습니다. 오버로드 가능한 연산자 집합과 같은 중요한 집합 은 별도로 제공됩니다. 이진 산술 표현과 같은 것에 대한 문법 규칙은 한 번에 하나씩 주어집니다.

기본적으로 "연산자"는 C ++ 언어에 공식적으로 의미가있는 범주가 아니므로 모든 범주 형 대답은 "느낌"에 따라 결정됩니다. 원하는 경우 연산자라고 부를 수 있지만 키워드 (또는 구두점!)라고 부를 수도 있으며 언어 표준에 동의하지 않습니다.


6
C 및 C ++ 표준은 많은 용어와 관련하여 조잡합니다. 독자들이 "최적화를 정당화하기 위해 그러한 생략을 사용할 수 있는지 여부를 샅샅이 뒤지기보다는 간격이나 모호함이있을 경우 의미하는 바를 추론 할 것이기 때문입니다." "표준의 작성자가 명시 적으로 금지 할 필요가 없다고 충분히 어리석은 생각을했을 경우.
supercat 2010 년

그런 식으로 인간적인 설명에서 표준은 모호 할 수 있지만 키워드가 operator있고 누군가가 정확한 묘사를 요구할 때 그 키워드와 함께 작동하는 것에 대해 영어 단어 "operator"를 사용하는 것이 타당하다고 생각합니다. 그런 의미에서, new, new[], delete, delete[], co_await, 객체에 대한 몇 가지 타입 변환 및 사용자 정의 리터럴의 전환은 운영자가 될 것입니다.
hemflit

@hemflit 연산자는 operator키워드 보다 이전이며 키워드 .와 함께 사용할 수없는 것을 포함 operator합니다. 내가 총구에서 "연산자"의 정의를 내 놓아야한다면, 내 마음은 "과부하 가능한 연산자"로 가지 않을 것이다.
Sneftel

모호한 영어 단어 "operator"의 @Sneftel 사용은 operator키워드 이전에 사용 됩니다. 연산자가 무엇인지 아닌지에 대해 절대적으로 정확한 묘사를해야만한다면, 문법에 정확히 정의 된 한 가지를 고를 것입니다. 일상적인 의사 소통에서 항상 그렇게 많은 정확성이 필요하지는 않습니다.
hemflit

나는 그것이 정확한 정의라는 것을 쉽게 인정할 것입니다. 그것은 단지 좋은 것이 아닙니다.
Sneftel

16

new-expressionnew 에서 사용되는 키워드 가 연산자 라고 말하는 것이 맞 습니까? 그 이유는 무엇?

아니요 newA의 새로운 표현은 식별하는 키워드입니다 새로운 표현 .

새로운 표현은 호출operator new 또는 operator new[]스토리지를 얻을 수 있습니다. 또한 해당 스토리지를 초기화하고 할당 해제합니다 ( operator delete또는operator delete[] ).

오버로드 가능한 사용자 교체 가능 함수와 새로운 표현식operator new 으로 만 언급 된다는 점에서 분명한 차이가 있습니다. 은이 함수를 호출하는 것 이상을 수행합니다.

참조 : 7.6.2.8/10 [expr.new]

새로운식이 할당 함수를 호출하여 객체에 대한 스토리지를 획득 할 수있다 ( [basic.stc.dynamic.allocation]). 는 IF 새로운식이 예외 발생에 의해 종료, 그것을 해제 함수를 호출하여 저장을 해제 할 수있다. 할당 된 유형이 비 배열 유형 인 경우 할당 함수의 이름은 다음과 같습니다.operator new 이고 할당 해제 함수의 이름은 operator delete입니다. 할당 된 유형이 배열 유형 인 경우 할당 함수의 이름은 다음과 같습니다.operator new[] 이고 할당 해제 함수의 이름은 operator delete[]입니다.


반례를 통해 우리는

T operator+(T, T);
void* T::operator new(std::size_t);

일부 유형 T의 경우 다음 형식 중 하나를 추가합니다.

T a, b;
T c = a + b;
T d = T::operator +(a, b);

동일합니다. 중위 표기법은 연산자 호출에 대한 구문 설탕 일뿐입니다.

그러나 할당은 매우 다르게 작동합니다.

T *p = new T;
// does much more than
void *v = T::operator new(sizeof(T));

따라서를 호출하기 위해 new-expression 구문 설탕 을 호출하는 것은 합리적이지 않습니다 operator new. 따라서 new키워드는 단순히 호출 할 함수를 선택하는 것이 아닙니다. 그럴 수 없거나 operator delete호출 될 수 있는 함수 를 언급해야 합니다.


2
" operator new은 오버로드 가능한 연산자입니다"— 맞습니까?! 나는 그렇게 생각하지 않는다 : operator + is not a overloadable operator — +is, and you define overloads via a function called operator +.
Konrad Rudolph

1
아니요, 연산자는 new-expression의 일부로 호출되는 특정 함수임을 지적하여 대답했습니다. new-expression은 키워드로 식별되는 표현식이며 호출하기에 적합한 연산자를 찾습니다.
쓸모없는

1
나는 new그것이 new-expression에 나타나는 것처럼 키워드 의 상태를 어떻게 해결하는지 아직 보지 못하고 있습니다.
John Bollinger

6
사실, 사실 new연산자 오버로딩의 대상이 대답이 있어야 할 것을 제안 , new(자체) 연산자이다.
John Bollinger

2
표준은 연산자를 호출하는 표현식 만 참조합니다. 재귀 적이 지 않으면 똑같을 수 없습니다. 그래서 간결한 해석은 표현과 연산자가 정확하고 표준이 말하는 그대로라는 것입니다.
쓸모없는

12

난 단지 그것을 부를 것이다 새로운 표현 으로 피하기 혼란 void* operator new ( std::size_t count )만을 프로세스의 일환으로 메모리를 할당하는 새로운 표현 송장 (할당 메모리, 시작 수명, 생성자 호출)을 .

의 문제 new는 단순히 operator new. 조금 때문에 혼란스러워하는 통화 만 .x + y+operator +


9

이것은 의해 지배된다 [expr.new] , 명확하게 구별되는 새로운 표현 방법 새로운식이에 의해 저장 용량을 얻을 수있다 할당 함수 호출 명명된다 operator new. 특히, [expr.new] / 8에서 [ emphasis mine] :

새로운식이 기억 얻을 수 할당 함수를 호출하여 객체를 ([basic.stc.dynamic.allocation를]). new-expression이 예외를 던져 종료되면 할당 해제 함수를 호출하여 스토리지를 해제 할 수 있습니다. 할당 된 유형이 비 배열 유형 인 경우 할당 함수의 이름은operator new 이고 할당 해제 함수의 이름은 연산자 삭제입니다. 할당 된 유형이 배열 유형 인 경우 할당 함수의 이름은 operatornew[] 이고 할당 해제 함수의 이름은 operator delete[]입니다.


new새 표현식에 사용 된 키워드 가 연산자 라고 말하는 것이 맞 습니까?

특히, [expr.new] / 4 의 비 규범 적이기 는하지만 이 함수를 연산자 함수로 설명합니다. "[...] new연산자" :

[...] 대신, 명시 적으로 괄호로 묶인 새 연산자를 사용할 수 있습니다. [...]


3
답변 해주셔서 감사합니다. 제가받은 답변의 수를 보면이 질문에 어떤 식 으로든 답할 수있는 엄격한 언어가없는 것처럼 보이기 시작했습니다. 따라서 비 규범 적 텍스트가 최상의 증거가 될 수 있습니다.
François Andrieux

8

아니.

음, 일종의 네의 고려 사람들이 존재한다는 의미에서 newnew int연산자로합니다. 그러나이 의견은 (대부분) 표준과 상충됩니다.

먼저 [lex.operators/1]언어로 된 연산자를 나열합니다. 이것들이 단지 "전처리 연산자"라고 생각하도록 속지 마십시오. 어휘 연산자 의 의미에서 그러한 구별은 존재하지 않습니다 . 예를 들어 ++매크로 를 사용할 수 없기 때문에 말도 안됩니다 .

new사실 키워드 (당 [lex.key/1])입니다.

다음으로 새로운 표현 자체를 살펴 보겠습니다 . 이것은 일이 조금 더 울퉁불퉁 해지는 곳입니다. 예를 들어에는 다음과 같은 문구가 있습니다 [expr.new/4].

대신, 명시 적으로 괄호로 묶인 new 연산자 버전을 사용하여 복합 유형의 개체를 만들 수 있습니다.

위에 제공된 정의와 상충되고 해당 섹션의 다른 곳에서는 발생하지 않기 때문에 편집 오류라고 생각합니다.

그런 다음 연산자 오버로딩에 도달합니다 . 연산자 선언에 대한 문법적 생성에서 사물을 나열하는 터미널 (포함 new)의 이름은 연산자 ( [over.oper.general/1])입니다. 나는 우리가 이것에 대해 걱정할 필요가 없다고 생각합니다. 문법에서 터미널의 이름은 용어 정의를 소개하기위한 것이 아닙니다. 결국, _ 비트 AND 연산 일 필요 가없는 and-expression 이 있습니다. 그것은 단지 등식 표현 일 수 있습니다 :

and-expression :
   같음-표현
   및-표현 & 같음-표현

이와 같은 문법을 정의하는 것이 일반적이며 모든 등식 표현 이 어떻게 든 비트 AND 연산자의 호출로 간주 된다는 것을 의미하지는 않습니다 .

마지막으로, 일부는 (연산자 오버로딩 섹션에있는) 다음 문구 new가 이제는 고립 된 상태에서 마술처럼 연산자 라는 증거라고 주장했습니다 .

연산자는 new[], delete[], (), 및 []하나 이상의 토큰에서 형성된다

그들에게 나는 그것이 new나열되지 않았을뿐만 아니라 , new그 자체 가 여전히 운영자가 아니더라도 "과부화 될 수있는 것"의보다 넓은 의미에서 "연산자"라는 용어를 분명히 사용하고 있다고 말한다 . 또한 여러분이 알아야 할 모든 것을 알려주는 비 규범 적 메모에 있습니다.

그리고 당신이 지적했듯이 우리는 이미 operator new다른 것으로 간주 합니다.


1
[lex.operators]는 명확하게 불완전합니다 (완전 함을 의미하지 않습니다!). [expr.sizeof]는 그것이 sizeof연산자 라고 규범 적으로 말하고 있기 때문입니다. [expr.throw]는에 대해 덜 명시 throw적이지만 여전히 "연산자"를에 대해 말하며 throw이는 throw연산자 임을 의미합니다 .
Konrad Rudolph

7

의미 론적 답변을 찾고 있다는 것을 알고 있지만, "키워드"(명확하게 예약되어 있음)라고 말하고 우리 둘 다 메모리 할당을위한 단순히 C ++ 구조라는 것을 알고 있다고 가정합니다. 즉, C ++의 "연산자"를 생각할 때 특정 유형에 대해 재정의 할 수있는 입력 / 출력이 설정된 함수를 생각하는 경향이 있습니다. new는 모든 유형에 대해 동일합니다 (더 혼란스럽게도 재정의 될 수 있음).

공식 cppreference가 얼마나되는지 확실하지 않지만 :

new-expression은 적절한 할당 함수를 호출하여 스토리지를 할당합니다. type이 배열이 아닌 유형이면 함수 이름은 operator new입니다. type이 배열 유형 인 경우 함수 이름은 operator new []입니다.

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

그 다음에 new <type>는 메모리를 할당하는 표현식이고 그 표현식에 new대한 연산자 는 다음과 같습니다 .

동일한 논리 사용 :

  • sizeof표현식에 대한 "연산자"입니다 sizeof(<type>)( sizeof"컴파일 시간"연산자이지만 우리가 익숙한 것과 약간 다릅니다)
  • + 표현식에 대한 연산자입니다. <type> <operator> <type>
  • throw 표현식에 대한 연산자입니다. throw <throwaable>

그 논리에 따르면 []()연산자도 있습니까? 인가 for? 인가 throw?
Konrad Rudolph

1
@KonradRudolph 그래 내가 말을 []하고 ()별도의 연산자를 구성한다. 다시 한 번 for절대적으로 키워드이지만 운영자가되는 것을 부정 할 수있는 부분은 재정의 할 수있는 첫 번째 부분이었습니다. 기술적 으로 sizeof는 연산자가 아닙니다. 이는 전처리 표현식에 가깝다는 점에서 C ++의 사실입니다. 그리고 throw식의 연산자입니다throw <throwable>
Rogue

[]()람다를 정의 할 때 특별히 조합을 의미 했습니다. 하지만 당신의 대답은 재미 있기 때문에 (C ++에서) 대답은 상황에 따라 달라집니다 또한 :에 foo(), ()(! overloadable) 연산자; 으로 (1 + 2)는 전혀 운영자 아니다 (특히 다른 언어에있어서, R은,이 다르다). 어쨌든 재정의 가능한 기준으로는 충분하지 않습니다. overloadable없는에도 불구하고 명확 운영자입니다 C에서 물건 ++의 많음이있다 ( ., ::, :?, 모두 sizeof 들, 등).
Konrad Rudolph

1
아, []()A와 람다 (내 C ++에 속도를 최대로 아니에요 특히 때문에) 정의하는 까다로운 짐승이다. 그래서 여기서는 여전히 [] ()람다 표현식 의 다른 연산자를 구성 한다고 말하고 싶습니다 .하지만 그것들을 재정의 할 수 없다고 주장 할 것인지, 아니면 람다를 구현 / 선언하는 행위가 기본 람다를 재정의하는 것을 구성하는지 확실하지 않습니다. 자바). 언어 디자인은 그곳에서 과학보다 약간의 예술이되기 시작합니다. 지금까지와 같은 ( ... ), 내가 사용했던 대부분의 랭 가문에서 분리, 그러나 나는 진짜 빨리 R에서 수컷 거위 할게요
악성

2
참고로 R에서는 모든 것이 함수이며 모든 것이 재정의 될 수 있습니다. 포괄적 인 규범 적 참조가 없으며 괄호가 연산자로 간주되는지 확실하지 않지만 재정의 할 수 있습니다. 사실, 표현식 (a + b)은 '(`(a + b) 또는 실제로`(`(`+`(a, b)) 함수 호출과 의미 상 동일합니다. 여기서`x`를 사용하여 이름을 만들 수 있습니다. x(중위 연산자와 같은) 특수하지 않고 함수 호출을 구문 적으로 준수합니다.
Konrad Rudolph
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.