C ++ 11에서 사용되지 않는 매개 변수


79

C ++ 03 및 이전 버전에서는 사용되지 않는 매개 변수에 대한 컴파일러 경고를 비활성화하기 위해 일반적으로 다음 코드를 사용합니다.

#define UNUSED(expr) do { (void)(expr); } while (0)

예를 들면

int main(int argc, char *argv[])
{
    UNUSED(argc);
    UNUSED(argv);

    return 0;
}

그러나 매크로는 C ++의 모범 사례가 아닙니다. C ++ 11 표준에 더 나은 솔루션이 있습니까? 매크로를 제거 할 수 있습니까?

모두 감사합니다!


11
확실한. 경고를 끄십시오.
Pete Becker

65
아니! 그거 하지마!
궤도의 경쾌함 경주

9
매크로를 인라인으로 확장하는 것보다 얼마나 더 나은가요? (void)argc;보다 짧고 명확UNUSED(argc);
데이비드 로드리게스 - dribeas는

22
내가 좋아하는 unused(argc, argv)template<class... T> void unused(T&&...){}. 명확하고 간결하며 매크로가 없습니다.
Xeo 2013-04-02

19
@MadScientist이지만 이름없는 인수를 남겨 두거나 이름을 주석으로 처리 할 수도 있습니다. void foo(int /*unused_arg*/, int used_arg)
kassak 2013

답변:


41

나는 그 목적으로 빈 본문을 가진 함수를 사용했습니다.

template <typename T>
void ignore(T &&)
{ }

void f(int a, int b)
{
  ignore(a);
  ignore(b);
  return;
}

심각한 컴파일러가 함수 호출을 최적화하기를 기대하고 경고를 표시하지 않습니다.


20
When Tis a template parameter, T&&is a universal reference that binds to any. 템플릿 매개 변수 는 무엇이든 바인딩 하는 범용 참조 입니다.
문헌 : Angew는 더 이상 자랑 SO의없는

4
+1 비록 그의 코멘트에서 Xeo 의 고급 버전이 언급되지 않았지만.
Christian Rau 2013

12
기본 제공 방법을 무시하는 이유는 무엇입니까? 매개 변수 이름을 생략하기 만하면됩니다.
Jack Aidley 2013

27
-1, 이것은 특히 매개 변수 이름을 생략 할 수있는 경우 우스꽝스럽고 불필요한 장치입니다. 솔직히, 이것이 어떻게 든 25 개의 업보를 가지고 있다는 것이 나를 괴롭 힙니다.
TC1 2013-04-03

5
@ TC1 이것은 코드가하는 일과 이유에 대해 코드를 명시 적으로 만듭니다. 사용하지 않는 매개 변수 나 변수를 사용하는 것은 코드에서 냄새가납니다. 경고를 끄면 코드 냄새가 더 커집니다.
dascandy

205

매개 변수 이름을 생략 할 수 있습니다.

int main(int, char *[])
{

    return 0;
}

그리고 main의 경우 매개 변수를 모두 생략 할 수도 있습니다.

int main()
{
    // no return implies return 0;
}

C ++ 11 표준의 "§ 3.6 시작 및 종료"를 참조하십시오.


12
의 경우 main매개 변수를 모두 생략 할 수 있습니다. 그리고 return그 문제에 대한 진술.
Mike Seymour

4
@MikeSeymour 실제로 return 문을 생략하는 것이 좋은 습관이라고 생각합니다.
jtepe 2013-04-02

6
@jotep 좋아, 내가 물어볼 게. 왜 그것을 좋은 습관이라고 생각합니까?
Peter Wood

6
거의 항상 테스트 케이스에서 main's return 0를 생략 하지만 거의 항상 return EXIT_SUCCESS프로덕션 코드에서 자체 문서화 를 작성합니다. 그것은 좋은 연습입니다!
궤도의 밝기 경주

30
이것은 나에게 가장 좋은 대답 인 것 같습니다. 매크로 나 템플릿을 사용하는 모든 것이 나중에 변수를 사용할 수 없다는 것을 보장하지 않습니다. 이 두 침묵 경고 제 (익명) 매개 변수 적 사용할 수 없음을 보장합니다.
Alnitak

51

거기 <tuple>C ++ (11) 사용에 대한 준비를 포함, std::ignore의는 (런타임 오버 헤드를 부과하지 않고 가능성이 매우 높다) 쓰기 우리를 허용하는지, 객체 :

void f(int x)
{
    std::ignore = x;
}

4
이것이 표준 라이브러리에 있으므로 사용자 지정 함수를 작성할 필요가 없다는 점을 고려하면 이것이 최상의 솔루션이라고 말하고 싶습니다!
BrainStone 2016

2
이 클래스는 "std :: tuple의 압축을 풀 때 std :: tie와 함께 사용하기위한 것입니다."이 사용 사례가 아닙니다. 나는 그것이 해결책이라고 말하고 싶지만 아마도 최선은 아닙니다.
Maestro

1
실제로 무시하는 것이 좋습니다. Ofc, 매개 변수를 제거 할 수 있으면 대신 제거하십시오 (모든 경우에 최상의 솔루션이 될 것입니다).
danger89

33

이 경고를 "비활성화"하려면 인수 작성을 피하고 유형 만 작성하는 것이 가장 좋습니다.

void function( int, int )
{
}

또는 원하는 경우 주석 처리 :

void function( int /*a*/, int /*b*/ )
{
}

명명 된 인수와 명명되지 않은 인수를 혼합 할 수 있습니다.

void function( int a, int /*b*/ )
{
}

17 ++ C 당신이 [[maybe_unused] 속성 지정, 같은 :

void function( [[maybe_unused]] int a, [[maybe_unused]] int b )
{
}

2
나는이 작업을 수행하는 데 사용하지만, 더 이상 사용하여 코드의 큰 덩어리를 주석 수 있기 때문에 신속 고통이된다/* ... */
Ponkadoodle을

1
사실이지만 최신 IDE에서는 자동으로 주석 처리 할 블록을 선택하면 각 줄의 시작 부분에 "//"가 추가됩니다. 이것이 Eclipse CDT가하는 일입니다. 개인적으로 저는 이름이없는 첫 번째 예만 사용합니다. (예를 들어 .h 파일의 선언에 이름을 넣을 수 있습니다).
Nikko

5
@Wallacoloo 큰 덩어리의 코드를 주석 처리하고 싶을 때 #if 0 ... #endif를 사용합니다.이 코드는 중첩이 허용되고 기존 / * ... * / 주석과 충돌하지 않습니다.
Dmitry Frank

1
@DmitryFrank 그리고 대부분의 편집기와 IDE #if 0는 전체 전 처리기 인텔리 센스를 지원하지 않더라도 특수한 경우로 블록을 회색 으로 표시하는 것을 지원합니다.
Thomas

30

동등한 것은 없습니다.

그래서 당신은 똑같은 오래된 옵션을 고수하고 있습니다. 매개 변수 목록에서 이름을 완전히 생략 할 수 있습니까?

int main(int, char**)

main물론 의 특정 경우에는 단순히 매개 변수 자체를 생략 할 수 있습니다.

int main()

GCC와 같은 일반적인 구현 관련 트릭도 __attribute__((unused))있습니다.


14

매크로는 이상적이지 않을 수 있지만 이러한 특정 목적에 적합합니다. 나는 매크로 사용을 고수하고 싶다.


6
+1 :이 경우 해를 끼치 지 않고 문제를 해결합니다. 나는 여기에 그것들을 사용하지 않을 이유 ( "매크로를 사용하지 않는다"라는 말도 안되는 근거없는 만트라를 넘어서)를 보지 못한다.
궤도의 가벼운 경주

1
매개 변수 이름을 완전히 생략하는 것보다 매크로의 이점은 무엇입니까?
Micha Wiedenmann 2013

1
@MichaWiedenmann : 일부 매개 변수는 일부 전처리 상수가 설정된 경우에만 사용할 수 있습니다 (일반적으로 디버그에서).
Matthieu M.

2
@MatthieuM .: 나는 MAYBE_UNUSED그 이유 때문에 매크로라고 부를 것 입니다; 일반적으로 "아래에서 이걸 사용하지 않아도 걱정하지 마세요"라고 말했더라도 상관하지 않지만 계속 사용합니다.
궤도의 경쾌함 경주

2
좋습니다. 올바른 것은 아마도 "HIDE_UNUSED_WARNING"이라고 부르는 것입니다. 하지만 여기에서 매크로를 사용하는 것이 완벽하게 유효한 아이디어라고 생각합니다. 다른 코드와 혼동 및 / 또는 충돌을 일으키지 않는 방식으로 매크로의 이름이 지정되는 한.
Mats Petersson 2013-04-02

13

구식 및 표준 방식에 대해 무엇을 가지고 있습니까?

void f(int a, int b)
{
  (void)a;
  (void)b;
  return;
}

일부 컴파일러는 이것에 만족하지만 일부 컴파일러는 다른 컴파일러보다 까다 롭습니다. 크로스 플랫폼 작업은 모든 대상 OS 및 컴파일러에서 테스트하여 솔루션에 모두 만족하는지 확인해야합니다.
Jesse Chisholm은

12

새로운 것이 없습니다.

나에게 가장 적합한 것은 구현에서 매개 변수 이름을 주석 처리하는 것입니다. 이렇게하면 경고는 제거되지만 매개 변수가 무엇인지에 대한 일부 개념은 유지됩니다 (이름을 사용할 수 있으므로).

매크로 (및 기타 모든 Cast-to-void 접근 방식)에는 매크로를 사용한 후 실제로 매개 변수를 사용할 수 있다는 단점이 있습니다. 이로 인해 코드 유지 관리가 더 어려워 질 수 있습니다.


12

Boost 헤더 <boost/core/ignore_unused.hpp>(Boost> = 1.56)는이를 위해 함수 템플릿을 정의합니다 boost::ignore_unused().

int fun(int foo, int bar)
{
  boost::ignore_unused(bar);
#ifdef ENABLE_DEBUG_OUTPUT
  if (foo < bar)
    std::cerr << "warning! foo < bar";
#endif

  return foo + 2;
}

PS C ++ 17에는 [[maybe_unused]]사용하지 않는 엔티티에 대한 경고를 억제 하는 속성이 있습니다.


1
[[maybe_unused]]현재 가장 좋은 방법입니다.
Tomilov Anatoliy 2016

0

다른 디버그 빌드가있을 때 (예 : 어설 션을 활성화하여 빌드하려는 경우) 더 잘 제어 할 수 있기 때문에 매크로를 사용하는 것을 정말 좋아합니다.

#if defined(ENABLE_ASSERTS)
  #define MY_ASSERT(x) assert(x)
#else
  #define MY_ASSERT(x)
#end

#define MY_UNUSED(x)

#if defined(ENABLE_ASSERTS)
  #define MY_USED_FOR_ASSERTS(x) x
#else
  #define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x)
#end

다음과 같이 사용하십시오.

int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar))
{
  MY_ASSERT(myChar < 12.0f);
  return myInt;
}

0

시간이 중요한 코드 세그먼트에 대한 자체 구현이 있습니다. 나는 느리게하기 위해 시간이 중요한 코드를 잠시 연구 해 왔으며이 구현은 내가 최적화 한 시간에 중요한 코드에서 약 2 %를 소비한다는 것을 발견했습니다.

#define UTILITY_UNUSED(exp) (void)(exp)
#define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1)
#define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0

시간이 중요한 코드는 ASSERT*디버그 목적으로 정의를 사용 했지만 릴리스에서는 명확하게 잘라 냈지만 ...이 코드는 Visual Studio 2015 Update 3다음 에서 조금 더 빠른 코드를 생성하는 것 같습니다 .

#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0)
#define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)

그 이유는 이중 false ?표현입니다. 어떻게 든 최대 최적화로 릴리스에서 약간 더 빠른 코드를 생성합니다.

왜 이것이 더 빠른지 모르겠지만 (컴파일러 최적화의 버그로 보임) 적어도 해당 코드 사례에 대한 더 나은 솔루션입니다.

참고 : 여기서 가장 중요한 것은 릴리스에서 위의 주장이나 사용하지 않는 매크로 없이 시간이 중요한 코드가 느려진다는 것 입니다. 즉, 이중 false ?표현식은 놀랍게도 코드를 최적화하는 데 도움이됩니다.


-1

windows.hUNREFERENCED_PARAMETER를 정의합니다 .

#define UNREFERENCED_PARAMETER(P) {(P) = (P);}

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

#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}

또는 Windows 외부 :

#include <stdio.h>
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}

6
operator=부작용이있을 수 있기 때문에 이것은 매우 좋은 선택이 아닙니다 .
Tamás Szelei
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.