2012-11-24 1 views
1

을 :: 바로 f(t)가 호출 될 때 t의 값이 멀리 이동 한 이후초기화 목록 및 표준 앞으로

class D { /* ... */ }; 

int f (const D & t) { return /* something calculated from t */; } 

template<class T> 
class C { 
private: 
    int m_i; 
    T m_t; 
    // or first m_t, then m_i -- careless order of declarations 
public: 
    template<class T_> 
    C (T_ && t) : m_t (std::forward<T_> (t)), m_i (f (t)) { 
    } 
}; 

C<D> c (D()); 

버그로 이어질 수 있다는 가정에서 나는 건가요? (i) 공장 기능을 사용하거나 (ii) m_im_t이 선언 된 순서에 대한 종속성을 소개하는 것과는 별도로이 문제를 피할 수있는 방법이 있습니까?

+0

선언을 재정렬하고'f (m_t) '를 사용하는 것은 잘못된 일입니까? 그것도 의미가있는 유일한 것 같다. ('T'를위한 명시 적 생성자를 생각해 보라). –

+0

나쁜 스타일과 오류가 발생하기 쉬운 것으로 생각했습니다. – JohnB

+0

글쎄, 당신이 필요로하는 것이 필요합니다. * 프로그래밍 *은 오류가 발생하기 쉽습니다. 나는이 디자인이 마음에 들지 않는다. ('f'와'T_'의 이상한 관계는 무엇인가?).하지만 그것이 당신이 필요로하는 것이라면, 당신은 그것을해야만한다 ... –

답변

3

우선은 초기화 목록의 평가 순서는 클래스 정의에서 멤버의 순서에 의해 결정된다는 것이다, 귀하의 경우, 그래서이 될 것입니다 : 그래서

template<class T_> 
C (T_ && t) 
    : m_i (f (t)), m_t (std::forward<T_> (t)) { 
} 

를 귀하의 경우 그것은 괜찮습니다. 멤버 m_i 먼저 초기화

T m_t; 
int m_i; 
template<class T_> 
C (T_ && t) 
    : m_t (std::forward<T_> (t)), m_i (f (m_t)) { 
} 
+0

프로그래밍 스타일이 좋지 않습니까? – JohnB

+2

@ JohnB : 변수 정의에 주석을 추가하여 재정렬되지 않았는지 확인해야합니다. 일반적으로 평가 순서에 대한 의존성을 피하는 것이 더 좋지만,이 경우에는 의존성이 이미 존재합니다. 한 구성원의 초기화는 'std :: forward'로 평가할 때나 다른 평가가 아닌지에 따라 달라질 수 있습니다. *움직임*. –

+0

나는 이런 식으로 글을 쓰려고했지만, 그 해결책은'T'가'D'로 변환 될 것을 요구하는 반면, 원래의 것은'T_'만이 필요했습니다. 그래서 그것들은 미묘하게 다릅니다. 비록 내가 디자인을 이해한다고 주장하지는 않지만. –

2

과 시간 값이 명확하게 이동되지 않습니다 : 당신이m_i 전에 m_t선언 될 수 있도록 구성원을 다시 정렬하고 초기화에 m_t을 사용하는 경우에도 괜찮을 것 그것도 움직이지 않을 것이다. m_t(std::forward<T>(t))을 초기화하면 t 값을 사용하지 않는다고 암묵적으로 약속합니다 (적어도 새 값을 지정할 때까지).

일반적으로 실행 순서가 중요하며 이는 멤버 이니셜 라이저 목록에서도 마찬가지입니다. 즉, 멤버 간의 의존 관계를 소개 할 때 멤버를 선언하는 순서에주의해야합니다.

+0

미안하지만 잠재적 인 버그를 소개하기 위해 회원 선언을 다른 방향으로 돌리는 것이 아이디어였습니다. – JohnB