2010-11-26 2 views
2

있습니까 : 즉나는이 같은 구문을 찾고 있어요 명시 사본

class Hugo 
{ 
    Hugo(); 
    explicit Hugo(const Hugo& hugo); 

    Hugo GetRandomHugo() 
    { 
     Hugo hugo; 
     hugo.value = rand(); 
            // this would fail: 
            // return hugo; 

     return Hugo(hugo);  // explicit copy!! 
    } 
};

이 : 나는 경우에도 방법은 사본을 반환 할 수 있도록하는 명시 적 복사 구문을 찾고 있어요 내 복사 생성자는 명시 적입니다.

GCC 4.4.5를 사용하고 있습니다.

고마워,

CHARLY

+1

코드의 현재 상태는 어떻습니까? – Puppy

+0

어떤 종류의 오류가 있습니까? – jwueller

+0

복사 생성자가 명시적인 이유는 무엇입니까? 그리고 "왜 복사 생성자를 명시 적으로 원하지만 암시 적 복사본을 수행하기를 원합니다"라고 말하는 이유는 무엇입니까? 생성자를 명시 적으로 만드는 모든 점은 암시 적 변환을 방지하는 것이지만 복사 생성자는 실제로 "변환"하지 않습니다. 초기화, 인수 전달 등을 지원하기위한 것입니다. –

답변

5

당신은 할 수는 : 값에 의해 반환은 암시 복사 건설입니다. 여기에서 반환은 암시 적으로 명시 적으로 복사 된 임시 복사본을 복사하려고 시도합니다. 8.5/12에서

:

The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent to the form :

T x = a;

+0

컴파일러에게 이렇게 문법을 사용하는 것이 합리적이지 않습니까? "예, 명시 적으로 복사하고 싶습니다." – Charly

+1

@Charly : 우리는'T x (a)'(직접 초기화입니다. 쓴). 어떤 점에서, 여기서 문제는'return' 문이 추가 초기화를 숨기고 * 필연적으로 복사 초기화라는 것입니다. – icecrime

+0

@Charly : 왜 그런가요? 어쨌든, 컴파일러는 그것들을 삭제할 수 있기 때문에 복사는 투명하게 처리되어야한다 (그러나 여전히 접근 가능한 복사 생성자를 찾을 필요가있다). –

1
return Hugo(hugo); 

이 그냥 돌아 전에 하나 개의 추가 사본 을 만듭니다. 그런 다음 실제 return 문은 해당 사본을 취해 번을 다시에 복사합니다. 복사 생성자의 전체 점은 우리 또는 컴파일러가 객체 복사가 필요할 때마다 암시 적으로 사용할 수 있다는 것입니다.

명시 적 구문을 원하면 Clone() 또는 Copy() 함수를 클래스에 추가 할 수 있지만 복사 생성자를 바꿀 수는 없습니다.

컴파일러가 개체를 복사해야 할 때마다 (예 : 함수 매개 변수로 값을 전달하거나 함수에서 반환 할 때) 개체 복사본을 만들어야합니다. 호출자와 호출 수신자간에 "전환"코드가 표시되지 않기 때문에 컴파일러에서 수행 할 수있는 방법은 없습니다. 피 호출 함수 안에있는 주변의 개체를 복사하거나 외부에 복사 할 수 있지만 호출 수신자의 본문에서 호출자에게 복사 할 방법이 없습니다. 컴파일러 만이 그렇게 할 수 있습니다. 그러기 위해서는 에 복사 할 수 있어야합니다.이 작업은 복사 생성자를 통해 수행됩니다.

3

당신은 이제 다음과 같은 의미가

Hugo a; 
Hugo b = a; // forbidden 
Hugo c(a); // allowed 
Hugo d = HugoCopy(a); // allowed 

Hugo f() { 
    Hugo a; 
    return a; // forbidden 
    return HugoCopy(a); // allowed 
} 

또는 적용되는 다음

class HugoCopy; 
class Hugo { 
public: 
    Hugo() { ... } 
    Hugo(HugoCopy const&); 
    explicit Hugo(Hugo const&) { ... } 
}; 

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
     :hugo(hugo) 
    { } 

    Hugo const& hugo; 
}; 

Hugo::Hugo(HugoCopy const&) { ... } 

같은 명시 적 HugoCopy 클래스를함으로써이 문제를 해결할 수 있습니다, 당신은 변환 기능을 사용할 수 있습니다

class Hugo { 
public: 
    Hugo() { ... } 
    explicit Hugo(Hugo const&) { ... } 
}; 

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
     :hugo(hugo) 
    { } 
    operator Hugo const&() { return hugo; } 

private: 
    Hugo const& hugo; 
}; 

이것은 C++ 언어의 미묘한 구석에 달려 있습니다. ge. 그래서 당신이 이것을 사용한다면, 당신은 당신이하고있는 일을 잘 알고 있거나하지 말아야합니다. 먼저 HugoCopy의 변환 함수 (또는 첫 번째 경우에는 Hugo의 생성자)를 호출하여 Hugo/Hugo const&이되고, 직접Hugo 개체를 가진 대상 Hugo 개체를 초기화합니다. GCC는 코드를 좋아하지 않지만, Clang과 Comeau/EDG는 위의 의미에 따라 그것을 받아 들인다.

관련 문제