2009-04-16 4 views
9

내가 컴파일러 나에게 많은 이해가되지 않았다 오류로 실행 :왜 사용하여 건설 공사를 auto_ptr은하지 않는 = 구문

#include <memory> 
using namespace std; 

auto_ptr<Table> table = db->query("select * from t"); 

오류 : 비 스칼라 유형 '테이블 *'에서 변환 '

auto_ptr<Table> table(db->query("select * from t")); 

그것은 내가 예상대로 작동 할 수없는 생성자의 definiton에 대해 무엇입니까 : 표준 : : auto_ptr은이 < 표> ', 그러나 다음 줄이하는 일을

을 요청? 초기화 된 선언은 생성자를 사용한다고 생각했습니다.

explicit 
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } 

답변

17

그것은 "명시 적"키워드입니다 :

내 생각 엔 당신이 다른 같은 후 여러 쿼리를 사용하도록 지정 양식을 필요로한다는 것입니다.

template <typename T> 
struct foo 
{ 
    explicit foo(T const *) 
    { 
    } 
}; 


template <typename T> 
struct bar 
{ 
    bar(T const *) 
    { 
    } 
}; 


int main(int argc, char **argv) 
{ 
    int a; 
    foo<int> f = &a; // doesn't work 
    bar<int> b = &a; // works 
} 

"명시 적"키워드는 생성자가 암시 적 유형 변환에 사용되는 것을 방지합니다. 다음 두 함수 프로토 타입을 고려 : 그 정의와

void baz(foo<int> const &); 
void quux(bar<int> const &); 

을 int 형 포인터로 두 함수를 호출하려고 :

baz(&a); // fails 
quux(&a); // succeeds 

을 quux의 경우, 사용자의 INT 포인터는 암시 적으로 바로 전환했다. 고려, 다른 사람들이 댓글을 달았 것에 다음 (오히려 바보) 코드를 확장하려면 : : 편집

무엇 로타에 추가

void bar(std::auto_ptr<int>); 


int main(int argc, char **argv) 
{ 
    bar(new int()); // probably what you want. 

    int a; 
    bar(&a); // ouch. auto_ptr would try to delete a at the end of the 
      // parameter's scope 

    int * b = new int(); 
    bar(b); 
    *b = 42; // more subtle version of the above. 
} 
+0

어. 내가 auto_ptr에 대한 사용 사실을 실제로 발견했다는 것을 확신 할 때, 그것은 디자인이 나를 얼굴에 때리게한다. 이전 삭제로 이동하십시오. –

+2

그 때문에 auto_ptr을 삭제하지 마십시오. 그냥 명시 적 생성자를 사용하십시오 : auto_ptr

테이블 (db-> query ("select * from t")); 또는 shared_ptr을 이동하십시오. – Eclipse

+1

생성자가 명시 적으로 필요한 이유가 있습니다. 우발적 인 실수로부터 당신을 보호합니다. auto_ptr을 (...)에두면 쉽게 사용할 수 있습니다. – lothar

8

당신이 템플릿 유형의에 대한 할당 연산자를 정의하지 않습니다

auto_ptr<Table> table = auto_ptr<Table>(db->query("select * from t")); 

auto_ptr은을 사용해야합니다

여기 내 auto_ptr의합니다 (SGI의 STL에서) 생성자입니다. 유일하게 허용 된 할당은 또 다른 auto_ptr에서옵니다 (포인터의 생성자는 명시 적입니다). 이는 auto_ptr이 메모리 소유권을 가정하기 때문에 실수로 auto_ptr을 잘못 사용하는 것을 방지하기 위해 수행됩니다.

// initialize using constructor 
auto_ptr<Table> table(db->query("select * from t1")); 
... 
// new query using assignment 
table = auto_ptr<Table>(db->query("select * from t2")); 
... 
// another query using assignment 
table = auto_ptr<Table>(db->query("select * from t3")); 
+1

왜 'auto_ptr

'테이블 (db-> query ("select * from t")); – avakar

+0

그는 그 자신을 생각했습니다 (그의 질문 참조). 그리고 하나 이상의 질의를 할 때마다 할당 폼이 필요합니다 :-) – lothar

+0

코멘트를 편집 할 수있는 방법이 있었으면합니다. 너는 빨리 타이핑 ;-) – lothar

2

말했다 다음 auto_ptr 생성자는 explicit 키워드로 선언되어 있기 때문에, explict 캐스트를 사용하여 원시 포인터에서 auto_ptr을 생성해야합니다. C++ 개발자)

5

생성자는 암시 적 유형 캐스팅 사용하지 않을 즉, 명시 적으로 선언된다. - (경험 explicit의 도입 전에 암시 적 캐스팅은 많은 새로운의 파멸이었다). auto_ptr 로의 암시 적 변환은 auto_ptr이 포인터의 소유권을 가지고 있기 때문에 쉽게 바람직하지 않은 상황을 초래할 수 있습니다.

예를 들어, auto_ptr이 암시 적 변환을 허용하고 실수로 auto_ptr을 사용하는 메소드에 포인터를 전달하면 포인터는 자동으로 auto_ptr로 변환되고 함수가 끝날 때 자동으로 포인터가 삭제됩니다. 의도.그러나 생성자를 명시 적 변환으로 표시하면 더 이상 자동으로 생성자를 호출 할 수 없으므로 소유권을 auto_ptr로 전달할 의도가 있음을 명확하게 나타내므로 잠재적 인 혼동을 피할 수 있습니다.

void fun(std::auto_ptr<Foo> foo) // Assume implicit conversion is allowed. 
{ 
    // do stuff with foo 
} 

Foo *foo = new Foo(); 

f(foo); // Normally this isn't allowed. 

foo->bar(); // Oops