2015-01-07 12 views
7

제 질문은 복사 생성자가없는 개체를 반환하는 방법에 대한 것입니다. 예를 들어, 힙에 앉아있는 bigResource이 있다고 가정 해 봅시다. unique_ptr을 사용하여 추적합니다. 이제 나는이 자원의 소유권을 애벌레에게 전합니다. 그런 다음 CaterpillarWithBigResource이 있습니다. 이제 어느 시점에서이 CaterpillarWithBigResourceButterflyWithBigResource으로 바뀌므로 Caterpillar 개체는 Butterfly 개체로 소유권을 이전해야합니다. 그들은 각각 unique_ptr이 때문에 Caterpillar이나 Butterfly도 기본 복사 생성자를 가지고복사 생성자가없는 개체를 반환하는 방법

#include <cstdlib> 
#include <iostream> 
#include <memory> 

class ButterflyWithBigResource { 
public: 

    // If I uncomment just this line, I get an error 
    // ButterflyWithBigResource(const ButterflyWithBigResource& other) = default; 

    // If I uncomment just this line, I get an error 
    // ButterflyWithBigResource(const ButterflyWithBigResource& other) = delete; 

    // With both above lines commented out, I get no errors, and the program runs fine. 

    ButterflyWithBigResource(std::unique_ptr<int>&& bigResource) : 
    bigResource(std::move(bigResource)) { 

    } 

    const int& getResource() { 
     return *bigResource; 
    } 

private: 
    std::unique_ptr<int> bigResource; 
}; 

class CaterpillarWithBigResource { 
public: 

    CaterpillarWithBigResource(int bigResource) : 
    bigResource(new int(bigResource)) { 

    } 

    ButterflyWithBigResource toButterfly() && { 
     return ButterflyWithBigResource(std::move(bigResource)); 
    } 
private: 
    std::unique_ptr<int> bigResource; 
}; 

/* 
* 
*/ 
int main(int argc, char** argv) { 
    CaterpillarWithBigResource caterpillarWithBigResource(5); 
    ButterflyWithBigResource butterflyWithBigResource(std::move(caterpillarWithBigResource).toButterfly()); 
    std::cout << butterflyWithBigResource.getResource() << std::endl; 
    return 0; 
} 

주의 사항 :

나는 상황을 모델링하기 위해 다음 코드를 작성했습니다. 그러나, 나는 이것이 문제가 될 것이라고 기대하지 않을 것이고, 단지 생성자 이동이 필요하다. 결국 나는 소유권을 Caterpillar에서 Butterfly으로 옮길뿐입니다.

g++ 버전 4.8.2을 사용하여 g++ -c -g -std=c++11 -MMD -MP -MF을 사용하여 프로그램을 컴파일하면 실제로 정상적으로 작동합니다.

그러나

이제 이상한 것은 내가 선 ButterflyWithBigResource(const ButterflyWithBigResource& other) = delete;을 추가하여 Butterfly 년대가 삭제 생성자를 복사 컴파일러를 생각 나게하는 경우이며, 프로그램은 더 이상 컴파일하지 않고, 컴파일러는, 그 복사 생성자가 삭제 불평 나는 할 수 있도록 toButterfly 방법의 Butterfly을 반환하십시오.

그런 다음 모든 내용이 ButterflyWithBigResource(const ButterflyWithBigResource& other) = default;이라는 줄을 사용하는 대신에 괜찮다고 알리려고하면 다시 동일한 오류가 발생합니다.

는 내가 일이 원하는 것은 toButterfly 이동의 반환 주소, 나중에 Butterfly의 인자로 사용하는 'main()butterflyWithBigResource를 구성 할 때의 이동 생성자 할 toButterfly 방법에 지어진 Butterfly입니다. 이것이 일어날 수있는 방법이 있습니까?

+0

BTW (당신이 작업 할당을 이동하려는 경우,도 및 이동 할당 연산자) 명시 적으로 이동 생성자 기본, 당신은 저작권법과 사용하십시오 리스트 초기화 :'return {std :: move (bigRes ource)}' – 0x499602D2

답변

7

명시 적으로 defaultdelete 복사본 생성자를 주석 처리 할 때 컴파일러는 자동으로 생성자 생성자 (및 할당 할당 연산자)를 생성 할 수 있습니다.

복사 생성자를 명시 적으로 default 또는 delete으로 지정하면 이동 생성자의 암시 적 생성을 억제합니다. N3337에서

, 클래스 X의 정의가 명시 적으로 이동 생성자를 선언하지 않을 경우 디폴트로 §12.8/9 [class.copy]

, 하나가 암시 적으로 선언 될 경우와
경우에만 - ...

- X는 사용자가 선언 된 복사 생성자,
이 없습니다

이동 생성자가 더 이상 생성되지 않으면 toButterfly()의 반환 값을 복사해야하지만 복사 생성자를 기본값으로 설정했는지 삭제했는지 여부에 관계없이 실패합니다.

default 복사 생성자의 경우 복사 할 수없는 unique_ptr 데이터 멤버가 있기 때문에 컴파일러에서 기본 복사 생성자 구현을 생성 할 수 없습니다.

delete 복사 생성자가 오버로드 확인을 통해 선택되면 오류입니다.


위의 설명은 unique_ptr 데이터 멤버의 존재가 암시을 삭제,하지만 당신은 그렇게하고 싶은 경우에, 당신은 또한해야합니다으로 당신은 명시 적으로부터 복사 생성자를 삭제할 필요가 없습니다

없음 복사 생성자와 객체를 반환하는

ButterflyWithBigResource(ButterflyWithBigResource&&) = default; 
ButterflyWithBigResource& operator=(ButterflyWithBigResource&&) = default; 

Live demo

+0

오케이 간단했다. –

+0

그걸 수정했습니다. 내 실제 코드에서'virtual ~ C() = default;'). –

+1

@NowIGetToLearnWhatAHeadIs * -'X'는 사용자가 선언 한 소멸자를 가지고 있지 않습니다. * – Praetorian