2013-06-06 3 views
10

지나치게 모호한 제목에 대해 유감스럽게 생각합니다 (영어 실력 부족). 더 나은 제목을 제안하십시오.왜 복사 생성자가 호출되지 않습니까?

다음 코드를 고려하십시오.

struct A { 
    typedef std::vector<double> State; 

    // template <class... Args> 
    // A(Args... args) 
    //  : a(args...) 
    // {} 

    template <class... Args> 
    A(Args&&... args) 
      : a(std::forward<Args>(args)...) 
    {} 

    A(const A&) = default; 
    A(A&&) = default; 

    State a; 
}; 

int main(){ 

    A a(3,2); 
    A b = a; // This line triggers an error!! 
} 

GCC 4.8.0 오류 메시지 error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...)와 함께 컴파일하지 못했습니다.

이 코드가 잘못된 이유를 이해할 수 없습니다. 제 생각에는 컴파일러는 라인 A b = a;에 복사 생성자를 호출해야합니다.

그러나 생성자를 주석 처리 된 것으로 대체하면 (값을 단순히 취함). 그것은 컴파일됩니다. 게다가 기본 복사 (및 이동) 생성자에 대한 행은 필요하지 않습니다. 여기 어떻게됩니까?

답변

9

를 복사 생성자를 호출 것 lvalue 또는 rvalue 참조인지 여부에 관계없이 모든 유형을 모든 cv 자격과 일치시키는 범용 참조를 만듭니다.

그래서 귀하의 경우에 당신은 A를 전달하고있어, 따라서 Args... = A &, 컴파일러는하지 않기 때문에, const A &보다 더 나은 일치 참조-붕괴 규칙에 A & 덕분에 Args &&... = A & &&, const가 아닌 변수에 constness를 추가해야합니다.

+1

오, 알았어요. 명확한 설명 주셔서 감사합니다. :) – Sungmin

3

이 경우 템플릿이 아닌 const 값이 필요하므로 템플릿 생성자가 더 적합하다고 생각합니다. 당신이 consta를 변경하는 경우는 컴파일러가 자동으로 (당신이 템플릿 생성자를 수행해야합니다으로) 템플릿 매개 변수를 추론 유형에 &&을 적용 가진 C++ 11에서 ...

const A a(3,2); 
A b = a; 
+0

다른 복사본 생성자 'A (A &) = default'를 추가해 주셔서 감사합니다. 그것은 잘 컴파일합니다. :) – Sungmin

관련 문제