사용하지 않는 반환 값을 무효화하는 이유는 무엇입니까?


112
int fn();

void whatever()
{
    (void) fn();
}

사용하지 않은 반품 가치를 무효화 할 이유가 있습니까, 아니면 완전한 시간 낭비라고 생각하는 것이 맞습니까?

후속 조치 :

꽤 포괄적 인 것 같습니다. 자체 문서화 코드가 주석보다 낫기 때문에 사용하지 않는 반환 값을 주석 처리하는 것보다 낫다고 생각합니다. 개인적으로 불필요한 소음 이니까이 경고를 끄겠습니다.

그것 때문에 벌레가 도망 치면 내 말을 먹어 볼게 ...

답변:


79

David의 대답 은이 함수가 반환하는 것을 알고 있지만 명시 적으로 무시하고 있음을 다른 "개발자"에게 명시 적으로 보여 주려는 동기를 거의 다룹니다.

이는 필요한 오류 코드가 항상 처리되도록하는 방법입니다.

C ++의 경우 전체 정적 캐스트 표기법을 사용하는 것이 과도하게 느껴지기 때문에 C 스타일 캐스트도 사용하는 것을 선호하는 유일한 장소라고 생각합니다. 마지막으로 코딩 표준을 검토하거나 작성하는 경우 오버로드 된 연산자 (함수 호출 표기를 사용하지 않음)에 대한 호출도 이것에서 제외되어야한다고 명시 적으로 명시하는 것도 좋습니다.

class A {};
A operator+(A const &, A const &);

int main () {
  A a;
  a + a;                 // Not a problem
  (void)operator+(a,a);  // Using function call notation - so add the cast.

이것은 내가 C 스타일 캐스트를 선호하는 유일한 장소입니다. 내 코딩 표준에서 "a + a;"에 (void)를 추가합니다. 너무 (물론 적절하게 parened, 물론 : p)
— Johannes Schaub-litb

8
주제에서 약간 벗어 났지만 왜 "a + a;"를 하시겠습니까? 반환 값을 사용하지 않고 그렇게? 그것은 나에게 부작용의 남용처럼 보이며 코드의 의도를 모호하게 만듭니다.
— Rob K

5
글쎄, 당신이 매일 사용할 것은 'a = a'가 될 것입니다. 이것은 객체에 할당 된 값을 반환합니다 (잘 작동하는 모든 클래스에 대해! :)). 또 다른 예는 os << "Hello World"<< std :: endl입니다. 그들 각각은 "os"개체를 반환합니다.
— Richard Corden

46

직장에서 우리는 함수가 반환 값을 가지고 있음을 인정하기 위해 그것을 사용하지만 개발자는 그것을 무시해도 안전하다고 주장했습니다. 질문에 C ++ 태그를 지정 했으므로 static_cast 를 사용해야합니다 .

static_cast<void>(fn());

컴파일러가 반환 값을 void로 캐스팅하는 한 의미가 거의 없습니다.


사용되지 않은 반환 값에 대한 경고를 억제합니까?
— Paul Tomblin

아니 그렇지 않아. @Mykola : GCC4를 사용하면 경고를 트리거하는 반환 값을 무시해서는 안된다는 속성을 첨부 할 수 있습니다.
— David Holm

2
나는 g ++를 사용하는데 그런 캐스트에도 경고를 준다.
— klew

2
어떤 경고 옵션을 사용합니까? -Wunused 값은 내 환경에서 경고가 트리거되지 않습니다
— Mykola Golubyev

VC ++에서는 경고를 억제합니다
— jalf

39

이 작업을 수행하는 진정한 이유는 lint 라는 C 코드에서 사용 된 도구로 거슬러 올라갑니다 .

가능한 문제를 찾고 경고 및 제안을 발행하는 코드를 분석합니다. 함수가 확인되지 않은 값을 반환하면 lint우연한 경우 경고합니다. lint이 경고 를 무음 으로 처리 하려면으로 전화를 (void)겁니다.


2
이 방법으로 시작했을 수 있지만 대부분의 도구에는 이와 같은 경고를 억제하는 다른 메커니즘이 있습니다. 또한-이것이 시작된 이유와 관계없이 특히 안전에 중요한 코드 영역 내에서 이것은 개발자의 의도를 "문서화"하는 일반적인 방법이되었습니다.
— Richard Corden

5
GCC는 -Wall을 사용하여 이에 대한 경고를 제공합니다.
— greyfade

23

캐스팅 대상 void은 사용되지 않은 변수 및 저장되지 않은 반환 값 또는 식에 대한 컴파일러 경고를 억제하는 데 사용됩니다.

Standard (2003)는 §5.2.9 / 4에서 다음과 같이 말합니다.

모든 표현식은 "cv void"유형으로 명시 적으로 변환 할 수 있습니다. 식 값이 삭제됩니다 .

따라서 다음과 같이 작성할 수 있습니다.

//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);

//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());

//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());

모든 양식이 유효합니다. 나는 보통 다음과 같이 짧게 만듭니다.

//suppressing  expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);

그것도 괜찮습니다.


1
컴파일러 경고를 항상 끄는 것은 아닙니다. gcc가 void로 캐스팅에 응답하지 않는 것 같습니다
— Matt

@Matt : 어떤 버전의 GCC를 사용하고 있습니까? ideone.com 또는 stacked-crooked.com (후자가 더 좋습니다)에 코드를 게시 할 수 있습니까?
— Nawaz 2013

1
표준 "버려진"문구는 경고가 린터에 의해 제기되지 않아야 함을 의미합니까?
— Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 : .... 흥미로운 질문입니다. 현재 나는 그것에 대한 답을 모릅니다. 어떻게 든 알게된다면 저와 공유 해주세요.
— Nawaz


4

Cast to void는 비용이 들지 않습니다. 컴파일러를위한 정보 일뿐입니다.


1
코드를 작성하는 시간과 이후에 코드를 읽고 이해하는 (그리고 무시하는) 시간이 무료라면 "비용이 들지 않습니다". IMO, 글쓰기는 (void)저에게 시간과 에너지를 소비하고 저자가 표현의 작동 방식을 알고 있는지 궁금해합니다.
— wallyk

4

프로그램의 기능을 위해 void로 캐스팅하는 것은 의미가 없습니다. 또한 David의 답변에서 제안한 것처럼 코드를 읽는 사람에게 신호를 보내는 데 사용해서는 안된다고 주장합니다. 당신의 의도에 대해 뭔가를 전달하고 싶다면 코멘트를 사용하는 것이 좋습니다. 이와 같은 캐스트를 추가하면 이상하게 보이고 가능한 이유에 대한 질문이 제기됩니다. 그냥 내 의견 ...


2
이것은 당신이 반환 값에 대해 신경 쓰지 않고 처리하는 것을 잊은 것이 아니라는 것을 다른 사람들에게 명시 적으로 알리는 알려진 패턴입니다.
— Spidey

For the functionality of you program casting to void is meaningless자기 설명서 및 컴파일 경고 수, 그것은 정말 아니다. 코드가 스스로 설명 할 때 you should not use it to signal something to the person that is reading the code [...] it is better to use a comment.가장 좋은 주석은 주석 없음 입니다. 그리고 다시 말하지만, 유효한 경고 컴파일러가 프로세스에서 행복하게 유지됩니다.
— underscore_d

'이런 캐스트를 추가하면 이상하게 보일뿐 가능한 이유에 대한 의문이 제기됩니다.' 나는 이것들 중 하나를 발견했고 이것이 내가 이것을 읽는 이유입니다. 훈련되지 않은 내 두뇌에 신비한 스택 남용처럼 보였습니다.
— mynameisnafe

1

또한 코드가 MISTA (또는 기타) 표준을 준수하는지 확인할 때 LDRA와 같은 자동 도구를 사용하면 반환 된 값을 명시 적으로 (void)로 캐스팅하지 않는 한 반환 유형이있는 함수를 호출 할 수 없습니다.


0

C ++ 17 [[nodiscard]]

C ++ 17은 속성으로 "반환 값 무시 비즈니스"를 표준화했습니다.

따라서 준수 구현이 항상 nodiscard주어진 경우에만 경고하고 그렇지 않으면 경고하지 않기를 바랍니다 .

예:

main.cpp

[[nodiscard]] int f() {
    return 1;
}

int main() {
    f();
}

엮다:

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp

결과:

main.cpp: In function ‘int main()’:
main.cpp:6:6: warning: ignoring return value of ‘int f()’, declared with attribute nodiscard [-Wunused-result]
    6 |     f();
      |     ~^~
main.cpp:1:19: note: declared here
    1 | [[nodiscard]] int f() {
      | 

다음은 모두 경고를 피합니다.

(void)f();
[[maybe_unused]] int i = f();

통화에서 maybe_unused직접 사용할 수 없었습니다 f().

[[maybe_unused]] f();

제공합니다 :

main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
    6 |     [[maybe_unused]] f();
      |     ^~~~~~~~~~~~~~~~

(void)캐스트 작업 표준에 의무적으로 표시되지 않지만 "격려"입니다 : 내가 의도적으로 [[nodiscard] 반환 값을 폐기 할 수 있습니까?

또한 경고 메시지에서 볼 수 있듯이 경고에 대한 한 가지 "해결 방법"은 다음을 추가하는 것입니다 -Wno-unused-result.

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp

물론 이와 같이 전 세계적으로 경고를 무시하는 것은 권장하지 않습니다.

C ++ 20은 또한 당신이 이유를 추가 할 수 있습니다 nodiscard같이 [[nodiscard("reason")]]:에서 언급 한 바와 같이 https://en.cppreference.com/w/cpp/language/attributes/nodiscard

GCC warn_unused_result속성

의 표준화 [[nodiscard]]이전과 C가 속성을 표준화하기로 결정하기 전에 GCC는 다음과 같은 기능을 구현했습니다 warn_unused_result.

int f() __attribute__ ((warn_unused_result));

int f() {
    return 1;
}

int main() {
    f();
}

다음을 제공합니다.

main.cpp: In function ‘int main()’:
main.cpp:8:6: warning: ignoring return value of ‘int f()’, declared with attribute warn_unused_result [-Wunused-result]
    8 |     f();
      |     ~^~

ANSI C는이에 대한 표준이 없기 때문에, ANSI C는 C 표준 라이브러리 함수는 속성이 없거나 따라서 구현 또는 표시되지해야하는지에 자신의 결정을 한 지정하지 않는 다음에 유의해야한다 warn_unuesd_result,하는 일반적 (void)으로 모든 구현에서 경고를 완전히 피하기 위해 표준 라이브러리 함수에 대한 호출의 반환을 무시 하기 위해 캐스트 를 사용해야하는 이유입니다 .

GCC 9.2.1, Ubuntu 19.10에서 테스트되었습니다.

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