C ++에서 변수를 선언 할 때 변수 이름을 괄호로 묶을 수있는 이유는 무엇입니까?


84

예를 들어 다음과 같은 선언이 있습니다.

int (x) = 0;

또는 그것도 :

int (((x))) = 0;

내 코드에서 다음과 유사한 조각이 발생했기 때문에 이것을 우연히 발견했습니다.

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

분명히 나는 C소멸자에서 유용한 일을 할 객체 를 만들고 싶었습니다 . 그러나 컴파일러는 유형 C (y);이있는 변수의 선언으로 취급 하므로 재정의에 대한 오류를 인쇄합니다 . 재미있는 것은 내가로 작성하는 경우이다 또는 무언가로 같이 가 의도 한대로 컴파일. 가장 현대적인 해결 방법은 물론 생성자 호출 에 사용하는 것 입니다.yCyC (y).f ()C (static_cast<B*> (y)){}

그래서 내가 그 후에 알아 냈 듯이 변수를 같은 int (x) = 0;또는 심지어 선언하는 것이 가능 int (((x))) = 0;하지만 실제로 이와 같은 선언을 사용하는 사람을 본 적이 없습니다. 그래서 저는 관심이 있습니다. 현재로서는 악명 높은 "가장 성가신 구문 분석"과 유사한 경우 만 생성하고 유용한 것은 추가하지 않기 때문에 그러한 가능성의 목적은 무엇입니까?


가능성의 "목적"은 아마도 파서를 단순화하는 것입니다.
— molbdnilo


1
@GSerg 내 질문의 텍스트가 링크 된 질문의 두 번째 답변에서 질문에 어떻게 대답하는지 웃기게되는데, 이러한 선언을 허용하면 예상치 못한 결과가 발생하는 예를 제공하기 때문에 :)
— Predelnik


이 함정에 들어갔다 : 뮤텍스가 주석 처리 된 것을 몰랐고 실수로 잘못된 괄호 선언을 작성했습니다. // std :: mutex std :: unique_lock <std :: mutex> (m_mutex);
— Laurijssen 봉사

답변:


80

그룹화.

특정 예로서, 다음과 같은 함수 유형의 변수를 선언 할 수 있습니다.

int f(int);

자, 그런 것에 대한 포인터를 어떻게 선언 하시겠습니까?

int *f(int);

아니, 작동하지 않습니다! 이것은를 반환하는 함수로 해석됩니다 int*. 올바른 방법으로 구문 분석하려면 괄호를 추가해야합니다.

int (*f)(int);

배열도 마찬가지입니다.

int *x[5];   // array of five int*
int (*x)[5]; // pointer to array of five int

13
그리고 답을 완성하기 위해 : 질문자가 요청하는 특정 케이스를 허용하지 않는 것은 추가 특수 케이스 규칙이 필요합니다. ()유형의 작업 방식에 대한 현재 정의 는 유형 전체에서 동일합니다.
— Joseph Mansfield

따라서 특수한 경우는 가장 복잡한 구문 분석에 적용됩니다. 이것은 생성자 인수로 변수를 초기화하는 구문이 나중에 추가 되었기 때문입니다 (서둘러 요?).
— AnArrayOfFunctions 2015-04-16

1
@FISOCPP 음. . 예. C ++는 C 다음에 왔습니다.. .
— iheanyi

이 대답은 C ++뿐만 아니라 C에도 똑같이 적용됩니까?
— kdbanman 2015

" 함수 유형의 변수 "뭐? !!
— curiousguy

17

구문상의 관점에서 볼 때 선언은 항상 다음과 같이 보이기 때문에 일반적으로 이러한 선언에 괄호를 사용할 수 있습니다.

<front type> <specification>;

예를 들어, 다음 선언에서 :

int* p[2];

"전면 유형"은 int(아님 int*)이고 "사양"은 * p[2]입니다.

규칙은 "사양"부분에서 필요한만큼 괄호를 사용할 수 있다는 것입니다. 괄호는 때때로 명확하게하기 위해 불가피하기 때문입니다. 예를 들면 :

int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints

배열에 대한 포인터는 드물지만 함수에 대한 포인터와 동일한 상황입니다.

int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int

이것은 귀하의 질문에 대한 직접적인 대답입니다. 질문이과 같은 진술에 관한 C(y)것이라면 :

  • 전체 표현식을 괄호로 묶으 (C(y))면 원하는 것을 얻을 수 있습니다.
  • 이 명령문은이 지침이 종료 된 후 더 이상 지속되지 않는 임시 객체를 만드는 것 외에는 수행하지 않습니다.

1
내가 언급했듯이, 처음에는 소멸자에서 무언가를하고 있었는데, 일부 매개 변수를 설정하고 소멸자에서 모든 작업을 수행하기위한 "연결"기능이 몇 가지있을 때 꽤 표준적인 일이라고 생각합니다. 한 가지 더 해결 방법에 감사드립니다 {}. 결국 쓰기 가 가장 유효한 것 같습니다.
— Predelnik 2015

4
자신의 문법을 만드는 것을 피하고 표준에 제공된 문법을 사용하십시오. <front-type> <specification>오해의 소지가 있고 잘못되었습니다. 문법은<declaration-specifier> <declarator>
— Steve Cox

당신 말이 맞아요-나는 표준을 조사하지 않았고, 단지 내 머리에서 규칙을 반복했습니다. 실제로 C ++ 11에서의 역할은 키워드 <declaration-specifier>로도 수행 될 수 있으므로 auto항상 유형이 아닙니다.
— Ethouris

@Pravasi Meet : 내 게시물의 일부를 편집하고 주어진 구문 스키마에서 이름을 변경 한 경우 그에 따라 아래 3 줄의 이름도 변경하십시오. 그렇지 않으면 여전히 "전면 유형"과 "사양"이라는 오래된 이름이 있으므로 게시물이 의미가 없습니다.
— Ethouris
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.