g ++ -wreorder의 요점은 무엇입니까?
-
11-09-2019 - |
문제
g ++ -벽 옵션에는 -wreorder가 포함됩니다. 이 옵션이하는 일은 아래에 설명되어 있습니다. 누군가가 돌보는 이유는 분명하지 않습니다 (특히 -wall에서 기본적으로 이것을 켜기에 충분합니다).
-Wreorder (C++ only) Warn when the order of member initializers given in the code does not match the order in which they must be executed. For instance: struct A { int i; int j; A(): j (0), i (1) { } }; The compiler will rearrange the member initializers for i and j to match the declaration order of the members, emit-ting a warning to that effect. This warning is enabled by -Wall.
해결책
고려하다:
struct A {
int i;
int j;
A() : j(0), i(j) { }
};
지금 i
0이 아닌 알려지지 않은 값으로 초기화됩니다.
대안 적으로, 초기화 i
주문이 중요한 부작용이있을 수 있습니다. 예를 들어
A(int n) : j(n++), i(n++) { }
다른 팁
문제는 누군가가 생성자의 멤버 이니셔 목록을보고 해당 순서로 실행된다고 생각할 수 있다는 것입니다 (j 먼저, I). 그들은 회원이 클래스에서 정의 된 순서대로 실행됩니다.
당신이 썼다고 가정 해 봅시다 A(): j(0), i(j) {}
. 누군가가 그것을 읽고 내가 값 0으로 끝나고 생각할 수도 있습니다. 그것은 당신이 J로 초기화했기 때문에, 그 자체가 초기화되지 않았기 때문에 정크가 포함되어 있기 때문에 그렇지 않습니다.
경고는 당신이 쓰는 것을 상기시킵니다 A(): i(j), j(0) {}
, 희망적으로 더 많은 양고기처럼 보입니다.
다른 답변은 경고 옵션을 정당화하는 몇 가지 좋은 예를 제공했습니다. 나는 역사적 맥락을 제공 할 것이라고 생각했다. C ++의 제작자 인 Bjarne Stroustrup은 그의 책에서 설명합니다. C ++ 프로그래밍 언어 (제 3 판, 259 페이지) :
멤버의 생성자는 포함 된 클래스 자체 생성자의 본문이 실행되기 전에 호출됩니다. 생성자는 이니셜 라이저 목록에 나타나는 순서보다는 클래스에서 선언 된 순서로 호출됩니다. 혼란을 피하기 위해 선언 순서로 초기화기를 지정하는 것이 가장 좋습니다. 멤버 파괴자는 역 순서로 호출됩니다.
이니셜 라이저에 부작용이 있으면 물릴 수 있습니다. 고려하다:
int foo() {
puts("foo");
return 1;
}
int bar() {
puts("bar");
return 2;
}
struct baz {
int x, y;
baz() : y(foo()), x(bar()) {}
};
위의 내용은 직관적으로 순서가 이니셜 라이저 목록에 기록된다고 가정하더라도 "bar"그런 다음 "foo"를 인쇄합니다.
또는 if x
그리고 y
생성자가있는 일부 사용자 정의 유형이며, 해당 생성자는 부작용이 동일한 부작용이있을 수 있습니다.
또한 한 멤버 참조의 초기화가 다른 멤버를 참조 할 때 자체적으로 나타날 수도 있습니다.
생성자를 읽으면 경고가 있습니다. j
전에 초기화되고 있습니다 i
. 하나가 다른 사람을 초기화하는 데 사용되는 경우 문제가됩니다.
struct A {
int i;
int j;
A(): j (0), i (this->j) { }
};
생성자를 볼 때 이것 외모 안전한. 그러나 실제로는 j
초기화에 사용되는 시점에서 아직 초기화되지 않았습니다. i
, 따라서 코드는 예상대로 작동하지 않습니다. 따라서 경고.