if 문의 조건 부분에서 변수를 정의합니까?
나는 이것이 허용된다는 것에 놀랐습니다.
if( int* x = new int( 20 ) )
{
std::cout << *x << "!\n";
// delete x;
}
else
{
std::cout << *x << "!!!\n";
// delete x;
}
// std:cout << *x; // error - x is not defined in this scope
그래서 이것은 표준에서 허용합니까 아니면 컴파일러 확장입니까?
추신 : 이것에 대한 몇 가지 의견이 있었기 때문에- 이 예가 "나쁘거나"위험하다는 것을 무시 하십시오 . 나는 그것이 무엇 인줄 안다. 이것은 예로서 제 마음에 가장 먼저 떠오른 것입니다.
이것은 C ++ 98 이후 사양에서 허용됩니다.
섹션 6.4 "선택 문"에서 :
조건의 선언에 의해 도입 된 이름 (유형 지정자 -seq 또는 조건의 선언자에 의해 도입 됨)은 선언 지점부터 조건에 의해 제어되는 하위 명령문의 끝까지 범위에 있습니다.
다음 예제는 동일한 섹션의 것입니다.
if (int x = f()) {
int x; // ill-formed, redeclaration of x
}
else {
int x; // ill-formed, redeclaration of x
}
이전 C ++ 98 버전의 언어에서도 표준입니다.
실제로 대답은 아니지만 (주석은 코드 샘플에 적합하지 않습니다), 이것이 엄청나게 편리한 이유입니다.
if (int* x = f()) {
std::cout << *x << "\n";
}
API가 "옵션"유형 (부울 변환도 사용 가능함)을 리턴 할 때마다이 유형의 구성을 활용하여 해당 값을 사용하는 것이 적절한 컨텍스트 내에서만 변수에 액세스 할 수 있습니다. 정말 강력한 관용구입니다.
a의 조건 부분에서 변수의 정의 while
, if
그리고 switch
문은 표준입니다. 관련 절은 조건에 대한 구문을 정의하는 6.4 [stmt.select] 단락 1입니다.
BTW, 당신의 사용은 무의미합니다. new
실패하면 std::bad_alloc
예외 가 발생합니다.
다음은 if 조건 에서 선언 된 변수의 일반적이지 않은 사용을 보여주는 예 입니다.
변수 유형은 int &
부울로 변환 할 수 있고 then 및 else 분기 에서 사용할 수 있습니다.
#include <string>
#include <map>
#include <vector>
using namespace std;
vector<string> names {"john", "john", "jack", "john", "jack"};
names.push_back("bill"); // without this push_back, my g++ generated exe fails :-(
map<string, int> ages;
int babies = 0;
for (const auto & name : names) {
if (int & age = ages[name]) {
cout << name << " is already " << age++ << " year-old" << endl;
} else {
cout << name << " was just born as baby #" << ++babies << endl;
++age;
}
}
출력은
john was just born as baby #1
john is already 1 year-old
jack was just born as baby #2
john is already 2 year-old
jack is already 1 year-old
bill was just born as baby #3
불행히도 조건의 변수는 '='선언 구문으로 만 선언 될 수 있습니다.
이는 명시 적 생성자가있는 다른 유용한 유형의 경우를 배제합니다.
예를 들어, 다음 예제 std::ifstream
는 컴파일되지 않습니다 ...
if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile!
std::cout << "true: " << is.rdbuf();
} else {
is.open("c:/tmp/input2.txt");
std::cout << "false: " << is.rdbuf();
}
2019 년 1 월 편집 ... 이제 내가 할 수 없다고 설명한 것을 에뮬레이션 할 수 있습니다 ...
이것은 C ++ 11의 ifstream과 같은 이동 가능한 클래스 및 복사 제거 기능이있는 C ++ 17 이후의 복사 불가능한 클래스에서도 작동합니다.
2019 년 5 월에 편집 됨 : 자동을 사용하여 상세도 완화
{
if (auto is = std::ifstream ("missing.txt")) { // ok now !
std::cout << "true: " << is.rdbuf();
} else {
is.open("main.cpp");
std::cout << "false: " << is.rdbuf();
}
}
struct NoCpy {
int i;
int j;
NoCpy(int ii = 0, int jj = 0) : i (ii), j (jj) {}
NoCpy(NoCpy&) = delete;
NoCpy(NoCpy&&) = delete;
operator bool() const {return i == j;}
friend std::ostream & operator << (std::ostream & os, const NoCpy & x) {
return os << "(" << x.i << ", " << x.j << ")";
}
};
{
auto x = NoCpy(); // ok compiles
// auto y = x; // does not compile
if (auto nocpy = NoCpy (7, 8)) {
std::cout << "true: " << nocpy << std::endl;
} else {
std::cout << "false: " << nocpy << std::endl;
}
}
'Programing' 카테고리의 다른 글
CPU 사용량은 어떻게 계산됩니까? (0) | 2020.11.05 |
---|---|
Content-disposition을 사용하여 파일을 하드 드라이브에 강제로 다운로드하는 방법은 무엇입니까? (0) | 2020.11.05 |
조각 내부 클래스는 정적이어야합니다. (0) | 2020.11.05 |
서비스 / 팩토리에서 컨트롤러로 변수 바인딩 (0) | 2020.11.05 |
Android에서 외부 SD 카드에 쓰는 보편적 인 방법 (0) | 2020.11.05 |