문제

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, 따라서 코드는 예상대로 작동하지 않습니다. 따라서 경고.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top