2012-01-22 2 views
16

아마도 녹슬고 있습니다 (최근에 Python으로 작성했습니다).조건이있는 경우 변수를 선언 할 때 잘못된 점은 무엇입니까?

왜 컴파일되지 않습니까? i의 내가 서로를 얻을 int i=f() 주위 ()없이

if ((int i=f()) == 0) 

, 훨씬 더 합리적인 오류가 부울되지 않습니다. 그러나 그것이 내가 처음에 괄호를 원했던 이유입니다!

내 생각 엔 괄호를 사용하면이를 표현식으로 만들고 해당 선언문은 표현식에서 사용할 수 없다고 생각됩니다. 그렇지? 그리고 그렇다면 C++ 구문 신택스 중 하나입니까?

BTW, 나는 실제로이 일을하려고했다 : 범위에 문제가있다

if ((Mymap::iterator it = m.find(name)) != m.end()) 
    return it->second; 
+1

무엇이 잘못 되었나요? 모든 것 –

+5

@VJovic - 정교하고 유익한 답변으로 명성 점수를 받으면 방황합니다.) – davka

+0

아니요, 나는 부정적이 될 것입니다.) 그러나 진지하게 모든 표준 코딩 표준은 그러한 모호한 코드를 금지합니다. –

답변

37

당신은 C에서 if 문에서 변수를 선언 할 수 있습니다 ++ 만이 직접 초기화와 함께 사용하도록 제한하고 부울 값으로 변환해야합니다 :

이 이
if (int i = f()) { ... } 

C++ 어떤 수 아무것도하지 않습니다 "선언 표현식", 즉 변수를 선언하는 [하위] 표현식으로 설명 될 수 있습니다.

실제로, I는 표준의 조항 고개 초기화 두 형태는 6.4에 따라 지원된다 [stmt.select] 제 1

, 또한 기록 할 수있을된다
... 
condition: 
    expression 
    attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause 
    attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list 
... 

:

if (int i{f()}) { ... } 

분명히 C++ 2003에는 중괄호 초기화가 없으므로이 기능은 C++ 2011에서만 작동합니다.

+0

마지막 예가 합법적이라고 생각하지 않습니다. 'if (int i {f()}) {/*...*/}'또는'if (int i = f()) {/*...*/}'만 할 수 있습니다. _braced-init-list_는 중괄호를 포함해야합니다. (_braced-init-list_는 "{_initializer-list_, OPT}"또는 "{}")입니다. –

+0

@CharlesBailey : 네, 맞습니다. 어떻게 든 "braced-init-list"를 (...) 뜻으로 오해했습니다. 내가 고칠거야. –

+0

감사합니다, 합리적인 소리, 아래 @ 일리아의 대답은 몇 가지 근거를 제공합니다 – davka

20

.

다음 코드를 고려하십시오

if ((int a = foo1()) || (int b = foo2())) 
{ 
    bar(b); 
} 

블록 내에서 선언 b를인가? foo1()이 true를 반환하면 어떻게됩니까?

+0

내가 잊어 버린 것을 잊어 버렸습니다. 이것은 AFAIK이 범위를 만들지 않는 것처럼'()'와 같은 범위 문제라고 생각합니다. 나는 틀린가? – davka

+3

@SoapBox하지만 foo1이 1을 반환하고 단락 회로 평가 (내가 아는 한 보장됩니다)에서 'b'의 지정을 건너 뛰면 어떻게됩니까? – lccarrasco

+0

정확히 - 범위 문제를 해결하지 않으면 허용 변수를()로 선언 할 수 없습니다. C++의 변수는 선언이 '실행'될 때 시작되는 범위를 가지며이 상황에서는 결코 발생할 수 없습니다. – greggo

4

변수를 if 문 (또는 for 또는 while)에서 선언 할 수 있지만 바깥 괄호 블록에서만 변수를 선언 할 수 있으며 bool로 변환 할 수 있어야합니다.

(int i = 42;) 

초기화와 유효한 선언하지 않기 때문에

은 당신의 생각, 그것은 기본적으로 잘 허용하지 않는다된다. 당신은 하나의 추가 라인이 필요

,

Mymap::iterator it; 
if ((it = m.find(name)) != m.end()) 
    return it->second; 

하지만 당신이 정말로 다시이 줄을 원하는 경우 다음이 적어도,

Mymap::iterator it = m.find(name); 
if (it != m.end()) 
    return it->second; 

당신은 ifreturn 라인을 넣을 수 있습니다 작성하는 것이 좋습니다 나에게 이것은 가독성을 해치지 않지만 다른 사람들은 다른 것을 보게 될 것입니다.당신이 정말로, 정말로 반복자를 선언하고 if 상태에서 부울로 사용하려는 경우

, 당신은

if (struct { int it; operator bool() { return it != m.end; } } s = { m.find(name) }) 
    return s.it->second; 

할 수 있지만 ;-)이 유해가

0

그것은 사실이라고 생각 당신은

if ((int i=f()) == 0) 

을 쓸 수 있지만 완벽하게 쓸 수

그래서 당신은

if (int i=1 && (i=f()) == 0) 

i 0 이외의 값으로 초기화한다처럼 하나 개의 문장에서 두 작업을 수행 할 수 && 연산자를 사용할 수 있으며, 컴파일러가 왼쪽 적용되는 경우는 첫 번째 조건이어야한다 - 오른쪽 평가.

하지만 두 번째 예제에서 묻는 것처럼 iterator의 경우에는 적용 할 수 없습니다.