개발/C++

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

MinorMan 2020. 9. 24. 00:42
반응형

<질문>

int fn();

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

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

후속 조치 :

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

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


<답변1>

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.

<답변2>

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

static_cast(fn());

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


<답변3>

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

가능한 문제를 찾고 경고 및 제안을 발행하는 코드를 분석합니다. 함수가 확인되지 않은 값을 반환하면 Lint는 이것이 우연한 경우 경고합니다. 이 경고에서 Lint를 무음으로 처리하려면 호출을 (void)로 캐스팅합니다.


<답변4>

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

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

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

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

//suppressing unused variable warnings
static_cast(unusedVar);
static_cast(unusedVar);
static_cast(unusedVar);

//suppressing return value warnings
static_cast(fn());
static_cast(fn());
static_cast(fn());

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

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

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

그것도 괜찮습니다.


<답변5>

C ++ 17 이후로 void 캐스트 대신 사용할 수있는 [[maybe_unused]] 속성이 있습니다.


<답변6>

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


<답변7>

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


<답변8>

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


<답변9>

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();

f () 호출에서 maybe_unused를 직접 사용할 수 없었습니다.

[[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();
      |     ^~~~~~~~~~~~~~~~

(무효) 캐스트 작업은 필수는 아니지만 표준에서는 "권장"됩니다. [[nodiscard]] 반환 값을 의도적으로 버릴 수있는 방법은 무엇입니까?

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

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

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

C ++ 20을 사용하면 https://en.cppreference.com/w/cpp/language/attributes/nodiscard에 언급 된 [[nodiscard ( "reason")]]에서와 같이 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에서 테스트되었습니다.

반응형