2017-04-09 6 views
2

는 다음과 나는 다음과 같은 출력복사 생성자 대신 전달 참조 생성자가 호출되는 이유는 무엇입니까?

Something() 
Something() 
Something(SomethingType&&) 

왜 복사 생성자가 템플릿 전달 참조 생성자에 해결되고 얻을 코드

#include <iostream> 

using namespace std; 

template <typename Type> 
struct Something { 
    Something() { 
     cout << "Something()" << endl; 
    } 

    template <typename SomethingType> 
    Something(SomethingType&&) { 
     cout << "Something(SomethingType&&)" << endl; 
    } 
}; 

int main() { 
    Something<int> something_else{Something<int>{}}; 
    auto something = Something<int>{}; 
    Something<int>{something}; 
    return 0; 
} 

아니라 이동 생성자를 감안할 때? 이동 생성자가 암시 적으로 정의되었지만 복사 생성자가 아니라는 점을 짐작하고 있습니다. 그러나 복사 생성자가 스택 오버플로에서 암시 적으로 정의되지 않은 경우를 읽은 후에도 여전히 혼란 스럽습니다.

+1

이것은 매우 일반적인 블로그 주제입니다. https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/ – chris

답변

4

나는 이동 생성자가 암시 적으로 정의되었지만 복사 생성자가 아니기 때문에 그런 것 같아요.

아니요, 둘 다 클래스 Something에 대해 암시 적으로 정의됩니다. 복사 생성자는 파라미터로서 const Something& 걸리므

이유 복사 생성자는 템플릿 착신 기준 생성자

로 확인되고있다. 즉, 복사 생성자를 호출하려면 const 한정자를 추가하려면 암시 ​​적 변환이 필요합니다. 그러나 포워딩 참조 생성자는 Something&을 매개 변수로 사용하도록 인스턴스화 될 수 있습니다. 그러면 정확하게 일치하며 과부하 해결에서 승리합니다.

따라서 somethingconst을 만들면 전달 참조 생성자 대신 3 번째 경우에 대해 암시 적으로 정의 된 복사본 생성자가 호출됩니다.

LIVE

아니라 이동 생성자?

이동 생성자의 경우 위의 문제는 중요하지 않으므로 1 차 및 2 차 호출을 위해 암시 적으로 정의 된 이동 생성자와 전달 참조 생성자는 모두 정확히 일치하므로 비 템플릿 이동 생성자가 우선합니다.

+3

이러한 종류의 문제를 이해하는 데 매우 유용한 것으로 밝혀진 책은 [ 효과적인 현대 C++] (http://shop.oreilly.com/product/0636920033707.do) Scott Meyers 작성. –