모든 C ++ 연산자가 무언가를 반환합니까?


83

내가 함께 작업 한 모든 C ++ 연산자는 무언가를 반환합니다. 예를 들어 +연산자는 더하기 결과를 반환합니다.

모든 C ++ 연산자가 무언가를 반환합니까, 아니면 아무것도 반환하지 않는 C ++ 연산자가 있습니까?


7
이는 "연산자"라는 용어를 얼마나 좁게 정의 하느냐에 따라 다릅니다.
molbdnilo

12
이것은 표준에 의해 강제되지 않습니다. 예를 들어 +=return을 구현할 수 void있지만 권장되지는 않습니다. 또한 함수 호출 연산자가 반환 할 수 void있으며 이것은 유효합니다
Mircea Ispas

흠. 범위 해결 연산자 ::가 아무것도 반환하지 않는다는 직감이 있지만 확인하려면 표준을 참조해야합니다.
Yksisarvinen

2
질문의 컨텍스트는 C ++ 제공 유형에만 해당합니까, 아니면 사용자 정의 유형도 포함합니까?
Eljay

@Eljay C ++ 제공 유형 만.
user8240761

답변:


111

아니요, 모든 연산자가 무언가를 반환하는 것은 아닙니다.

그것들은 아마도 당신이 생각하는 것과 정확히 일치 하지는 않지만 , delete그리고 delete[]C ++ '키워드'는 실제로 연산자 라는 점에 유의하십시오 . 그리고 그들은 void반환 유형 을 갖는 것으로 정의됩니다 -이는 아무것도 평가 하지 않음 을 의미합니다 ( '무언가' 가 아님 ).

에서 cppreference :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;

13
나는 당신의 대답을 좋아합니다. 그것은 질문을 다르게 생각하게 만들었습니다. delete, delete[], throw, (void)x;캐스팅, 좌측 ,의 조작, 우측 ,조작 낳는 해당 void하는 ?:사용 삼원 throw아암 중 하나, dfri의 operator void()(정의 될 사용자)眠りネロク의 void operator()()(것이다 사용자 정의).
Eljay

10
delete연산자가 객체를 파괴 한 다음을 호출하는 것도 혼란 스럽습니다 operator delete. Ergo, delete운영자 및 operator delete별도의 것 :( stackoverflow.com/a/8918942/845092
Mooing Duck

7
삭제 연산자에 대해 이야기 할 때 삭제 기능을 왜 인용하는지 확실하지 않습니다. 하지만 뭐든.
Deduplicator

4
@MooingDuck 삭제 식은 개체를 파괴 한 다음 operator delete.
NathanOliver

삭제는 연산자로 간주됩니까? 객체가 전달되는 객체에 대해 작동하는 것이라고 생각합니까 ?? 삭제는 작업을 위해 전달되거나 생성 될 개체가 필요하지 않습니다 ..... printf .....처럼
Yunfei Chen

82

사용자 정의 유형의 연산자는 가장 이상한 작업을 수행하기 위해 오버로드 될 수 있습니다.

예를 들어 + 연산자는 더하기 결과를 반환합니다.

반드시 그런 것은 아닙니다.

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

여기서 멤버에 operator+왼쪽을 추가 value하고 반환 유형은 무효입니다. 이것은 구성된 예제이지만 일반적으로 사용자 지정 연산자에서 무언가를 반환하지 않는 것은 드문 일이 아닙니다.

오버로드 될 수 있고 내가 알고있는 무언가를 반환해야하는 유일한 연산자는 operator->. 원시 포인터 또는 operator->.


재미있게도 실제로는 오버로드 된 연산자 반환 값에 대한 제약이 없습니다. 따라서 연산자는 원하는 것을 반환 할 수 있습니다. en.cppreference.com/w/cpp/language/operators
bracco23

5
@ braccor23 operator->은 약간 특별하며 operator->다른 예외가 있는지 확실하지 않은 포인터 또는 객체를 반환 해야합니다
idclev 463035818

1
예, 그게 유일한 제약입니다. 비교 연산자를위한 bool도 아닙니다. 정말 이상해 보입니다.
bracco23

9
@ idclev463035818 : 식 템플릿이 더 유용한 예일 수 있습니다. 예를 들어, operator*(Matrix const& left, Matrix const& right)반환하지 Matrix않고 대신을 반환 하는 행렬 라이브러리를 만들 수 있습니다. MatrixMul그러면 이것이 operator+(Matrix const& left, MatrixMul const& right)연산에 공급되면 먼저 곱한 다음 더하는 것보다 더 효율적인 융합 곱하기 더하기가 될 수 있습니다.
Matthieu M.

1
@DarrelHoffman <<>>I를 위해 오버로드 / O 작업은, 그들은 당신이 그들을 계단식 할 수 있도록 스트림을 반환 할 것으로 예상하고 있습니다 :stream << foo << bar;
Barmar

34

간단히 말해서 연산자는 아무것도 반환하지 않습니다. 그것들은 언어로 표현을 만드는 데 사용하는 어휘 요소 일뿐입니다. 이제 표현식에는 유형이 있고 값으로 평가 될 수 있습니다. "물건을 반환하는"연산자가 이것이 의미하는 바라고 가정합니다.

그리고, 네. 유형이있는 C ++ 표현식이 있습니다 void(결과적으로 어떤 값으로도 평가되지 않음). 일부는 명백하고 다른 일부는 덜합니다. 좋은 예는

throw std::runtime_error()

throwC ++ 문법의 표현식입니다. 예를 들어 조건식과 같은 다른 표현식에서 사용할 수 있습니다.

return goodStatus() ? getValue() : throw std::runtime_error();

그리고 던지기 표현의 유형은입니다 void. 이로 인해 실행이 빠르게 다른 곳으로 이동하기 때문에 표현식은 가치가 없습니다.


21

기본 제공 C ++ 연산자 중 어떤 것도 반환 하지 않습니다. 오버로드 된 C ++ 연산자는 연산자 표기법이 함수 호출에 대한 구문 설탕 인 경우 무언가를 반환합니다.

오히려 연산자는 모두 무언가를 평가 합니다. 그 무언가는 잘 정의 된 유형을 가지고 있습니다. 도 함수 호출 연산자 void operator()(/*params*/)A는 void타입.

예를 들어 +'a'는 플랫폼 int에서 'a'인코딩 된 값을 가진 유형입니다 .

질문이 "C ++ 연산자가 void반환 유형을 가질 수 있습니까 ?"인 경우 그렇다면 대답은 확실히 그렇습니다.


14
@ idclev463035818 : 문제가있는 기간 반환 입니다. C ++에서 무언가를 반환하는 유일한 것은 함수입니다. 표현 무언가로 평가 됩니다.
Bathsheba

7
클래스 유형의 연산자는 무언가를 반환하는 메소드입니다
idclev 463035818

4
이것은 중요한 점입니다. 엉성한 용어는 혼란을 야기합니다. +1.
Pete Becker

3
@supercat — 귀하의 의견은 저를 포함하여 열심히 일하는 사람들을 비방합니다. 표준을 작성한 사람들은 컴파일러 작성자가 현재 또는 과거의 다른 컴파일러를 폴링하여 세부 사항을 입력 할 것을 기대 하지 않았습니다 . 표준의 목표는 C ++ 프로그래밍 언어의 구문과 의미를 명확하게 정의하는 것이었고 그 목적입니다. 예, 결과는 완벽하지 않습니다. 이전 버전에서 해결되지 않은 최신 표준에서 해결 된 많은 문제가 있습니다. 그것은 단순히 당시에는 볼 수 없었던 합병증을 인식하는 경험에서 비롯됩니다.
Pete Becker

3
@ Peter-ReinstateMonica — 여기에 더 강력한 버전이 있습니다. 표현식 I++은 값을 반환하지 않습니다. 의 유형이 i사용자 정의 유형 인 경우 해당 표현식은 operator++값을 반환하는 함수 인 으로 구현됩니다 . 당신은 그것을“구문 적 설탕”이라고 부릅니다. 나는 그것을 중요한 결과를 가져 오는 구별이라고 부릅니다.
Pete Becker

12

실제로 아무것도 반환하지 않도록 함수 호출 연산자 를 정의 할 수 있습니다 . 예를 들면 :

struct Task {
   void operator()() const;
};

17
거의 모든 연산자를 정의하여 아무것도 반환하지 않을 수 있습니다 (그리고 해당 코드를 유지해야하는 화난 폭도의 분노에 직면)
Yksisarvinen

7
@Yksisarvinen 그러나 적어도 이것은 잠재적으로 유용합니다.
Mark Ransom

11

연산자 void () : 사용자 정의 변환 함수 void로

operator void()컴파일러가 Tto voidconversion 함수 가 사용되지 않을 것이라고 경고 하는 독특한 변환 함수를 정의 할 수 있습니다 .

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

[class.conv.fct] / 1 에 의해 관리 됨

[...] 변환 함수는 (아마도 cv-qualified) 객체 를 (아마도 cv-qualified) 동일한 객체 유형 (또는 그에 대한 참조)으로, (아마도 cv-qualified) 기본 클래스 로 변환하는 데 사용되지 않습니다. 유형 (또는 그것에 대한 참조)의 나 (아마도 CV 정규화) void. 117

( 117 ) 이러한 변환은 과부하 해결 ([over.best.ics], [over.ics.ref]) 및 따라서 초기화 ([dcl.init]) 및 명시 적 캐스트를위한 표준 변환으로 간주됩니다. 로 변환 void은 변환 함수 ([expr.static.cast])를 호출하지 않습니다. 변환을 수행하기 위해 직접 호출되지는 않지만 이러한 변환 함수는 선언 될 수 있으며 잠재적으로 기본 클래스의 가상 변환 함수에 대한 호출을 통해 도달 할 수 있습니다.

그러나 위에 표시된 것처럼 명시 적 .operator void()구문을 사용하여 호출 할 수 있습니다 .


4

언어에 의해 정의 된 (내장) 연산자는 다양한 종류의 계산을 수행하는 데 사용되는 토큰입니다.

  • 산술 (+,-, *, /)
  • 증가 / 감소 (++,-)
  • 할당 (=, + =,-=, * =, / =, % =, >> =, << =, & =, ^ =, | =)
  • 논리 (!, &&, ||)
  • 관계형 (==,! =,>, <,> =, <=)
  • 조건부?
  • 반점

등등. 목록은 매우 광범위 할 수 있습니다.

같은 언어를 참고 문헌 이 하나 또는 이것 이 반드시 단순한 산술 또는 논리 수행하는 것을 복귀로 참조되지 않는 조작 변수를 의미하는 비교가 변형 될 수있다, 등등

이 연산은 어떤 값을 생성하기 때문에 연산자에 의해 "반환 된"것으로 해석 될 수 있지만 함수 반환 값과는 다릅니다.

반면에 오버로드 된 연산자는 일부 유형의 반환 값으로 정의 할 수 있습니다. 이는 void 일 수 있으므로 모든 연산자가 C ++에서 일부 값을 반환하지는 않습니다.


3

나는 당신이 언어의 구문 단위로서 연산자가 아니라 연산자 함수에 대해 이야기하고 있다고 가정하고 있습니다.

어떤 유형에서든 연산자를 오버로드하면 실제로 원하는 것을 반환 할 수 있습니다.

* 또는 ()와 같은 연산이 때때로 매우 직관적으로 입력 유형을 반환하지 않을 수 있기 때문에 이것은 또한 많은 의미가 있습니다. 복소수 유형과 실수 유형을 곱하는 것을 상상해보십시오. 또는 컬렉션에서 요소를 반환하는 연산자입니다.

또한 과부하 ++ 및 수 -하지에 사업자 따라서 제거 아무것도 반환 매우 부작용 표준 버전은 가지고 표현 값의 오류가 발생하기 쉬운 혼합.


2

아니요. 여기에서 다음 두 가지 예를 고려하십시오.

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

첫 번째 함수는 다른 함수에서 사용할 수있는 정수 값을 반환합니다. 값이 반환되고 필요할 때 사용할 수 있도록 메모리에 저장됩니다. 그렇지 않다면, 그것은 인간에게 보이지 않고 단지 기억 속에 행복하게 앉아 있습니다.

두 번째 기능은 기본 출력 장치 (일반적으로 콘솔)로 출력됩니다. 곱하기 연산자가 반환 한 값은 출력 장치로 전달됩니다. multiply_void 함수는 실제 값을 반환하지 않습니다.


0

모든 연산자는 무언가를 반환합니다. 그들은 무언가를 작동하기 때문에 연산자라고 불리며, 따라서 무언가를 반환합니다. 무언가를 반환하지 않는 연산자를 연산자라고 부를 수 없습니다. 상황에 따라 값을 반환하거나 True 또는 False를 반환합니다.


0

연산자 자체는 반드시 아무것도 반환하지 않습니다. 함수 호출은 값을 반환합니다. 연산자는 값을 생성 할 수 있습니다. 운영자는 때때로 함수를 호출 할 수 있습니다. 예는 다음과 같습니다.

• 함수 호출 연산자.

• 함수 호출로 변환되는 오버로드 된 연산자.

new-expression의 일부로 호출되는 new 연산자 는 함수 호출입니다.

함수 호출을 언급하는 유일한 목적은 결과와 반환을 명확히하는 것입니다. 126 개의 "return"인스턴스와 [expr] 에서 파생 된 단어를 모두 살펴본 결과 섹션에서는 return이라는 단어를 신중하게 사용하여 다음을 참조하는 것 같습니다.

• 함수 호출의 결과

• 코 루틴과 관련된 제어 흐름의 측면

좋아요, 결과 대 수익에 대한 충분한 pedantry입니다.


0

C ++ 연산자가 무언가를 반환하는지 여부는 사용 방법에 따라 다릅니다. 내장 C ++ 연산자는 void를 반환하도록 강제하지 않는 한 일부 값을 반환합니다.

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