2013-09-07 4 views
0

먼저 std :: auto_ptr에 3 가지 버전이 있는지 확인하십시오.왜 auto_ptr 비정상적인 동작

과 같이 표준 : : auto_ptr은의 첫번째 버전 :

template<class T> 
class auto_ptr 
{ 
public: 
    explicit auto_ptr(T *p = 0): pointee(p) {} 

    // copy constructor member 
    // template: initialize a new auto_ptr with any compatible auto_ptr 
    template<class U> auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {} 

    ~auto_ptr() { delete pointee; } 

    // assignment operator 
    // member template assign from any compatible auto_ptr 
    template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs) 
    { 
     if (&rhs != this) 
     { 
      reset(rhs.release()); 
     } 
     return *this; 
    } 

    T& operator*() const { return *get(); } 
    T* operator->() const { return get(); } 

    // return value of current dumb pointer 
    T* get() const { return pointee; } 

    // relinquish ownership of current dumb pointer and return its value 
    T* release() { T* p = pointee; pointee = 0; return p; }        

    // delete owned pointer,assume ownership of p 
    void reset(T *p = 0) 
    { 
     if (p != pointee) 
     { 
      delete pointee; 
      pointee = p; 
     } 
    } 
private: 
    T* pointee; 
};  

만 인터페이스를 구현 쉽게된다. 이 같은

내 코드 :

내 관점에서
auto_ptr<int> foo() 
{ 
    auto_ptr<int> p(new int(1)); 
    return p; 
} 

int main() 
{ 
    auto_ptr<int> p; 
    p = foo(); 
    return 0; 
} 

, 내 테스트 코드는 컴파일러를 전달할 수 없습니다. 그러나 그것을 지나쳤습니다. 그리고 그것을 실행할 때, 폰터를 두 번 삭제했습니다.

어셈블리 코드를 추적하고 아래의 흐름을 찾으십시오. 메모리 주소는 짧게 16 비트입니다.

ctor: f8e4  
new: 6bf0 
ctor: f7d4 

copy ctor: f7d4 -> f80c 
dctor: f7d4 (NULL) 
delete: 0 

lea ecx, [ebp-0ECh] // f8e4: memory-> 6bf0 

dctor: f80c (6bf0) 
delete: 6bf0 

dctor: f8e4 (6bf0) // twice delete 

코드 : p = foo(); 임시 객체를 ctor하고 foo()에 새로운 메모리를 보유합니다.

요점은 왜 p = foo()가 p.operator =()를 호출하지 않고 p.pointee를 변경해야하는 것입니까?

첫 번째 auto_ptr의 구현을 추가합니다. 나는 = 두 개의 연산자가 그 표준 : : auto_ptr은 찾을

template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs); 

사용

auto_ptr<T>& operator=(auto_ptr<T>& rhs) 

다른 것보다 :


순 친구와 이야기, 그는 mybe 컴파일러는를 생성하는 것을 지적했다. 그리고 필자는 수동으로 인터페이스에 추가하고 컴파일러 팁은 "auto_ptr '을'auto_ptr & '' '으로 변환 할 수 없습니다.

키입니다 !!! 그럼 왜 찾아야 해!


사용자가 연산자 유형을 클래스 유형으로 정의하지 않으면 컴파일러에서이를 생성합니다. 그리고 다른 연산자 =와 비교해보다 특별한 것을 선택하십시오!

해결! 모든 대답을 생각하십시오! 모든 의견을 주셔서 감사합니다!

+0

"구현이 쉽습니다"?? 'auto_ptr'의 구현을 보았습니까? –

+0

@Kerrek SB 예, 파일에서 gcc 또는 vs에서 찾을 수 있습니다. 대 버전 인 – mi2think

+1

@ mi2think를 보았습니다. 여전히 쉽다고 생각되면 [ auto_ptr_ref'] (http://stackoverflow.com/a/4514204/241631) 광기. – Praetorian

답변

0

나는, 내가 제대로 문제를 이해하지만 인터페이스는 실제로 사본 할당 연산자 (나 사본 생성자)를 정의하지 않는다는 것을하지 않도록 해요 "템플릿 복사 연산 때문에 = "은 실제 복사가 아닙니다 op = ("템플릿 복사 도구 "는 실제 복사 도구가 아닙니다).

#include <cstdio> 
using std::puts; 

struct M { 
    M& operator=(M const&) { 
     puts("M::operator=(M const&)"); 
     return *this; 
    } 
}; 

template<typename T> class Foo { 
    M m; 
    template<typename U> friend class Foo; // (needed for m = rhs.m; below) 
public: 
    template<typename U> Foo& operator=(Foo<U> const& rhs) { 
     puts("[template] Foo<T>::operator=(Foo<U> const&)"); 
     m = rhs.m; // calls M's op= 
     return *this; 
    } 
}; 

int main() { 
    puts("==="); 
    Foo<int> a; 
    Foo<double> b; 
    a = b; 
    puts("---"); 
    Foo<int> c; 
    Foo<int> d; 
    c = d; 
    puts("==="); 
} 

인쇄가 : 왜 두 번째 과제가 한 줄이

=== 
[template] Foo<T>::operator=(Foo<U> const&) 
M::operator=(M const&) 
--- 
M::operator=(M const&) 
=== 

여기에 문제를 표시하는 간단한 예제가? M::operator=에 컴파일러가 자동으로 생성 c = d; 진정한 사본 할당 연산자, 즉 Foo<int>::operator=(Foo<int> const&)를 호출하기 때문에 그건, 우리가 이 있기 때문에하지가 (만 템플릿 버전)을 선언 (회원 현명한 임무를 수행, 따라서 호출).

// ... 
    Foo& operator=(Foo const& other) { 
     puts("[non-template] Foo<T>::operator=(Foo<T> const&)"); 
     m = other.m; 
     return *this; 
    } 
}; 

를 한 후가 인쇄 :

따라서

, 나 클래스에 명시 적으로 추가해야합니다

=== 
[template] Foo<T>::operator=(Foo<U> const&) 
M::operator=(M const&) 
--- 
[non-template] Foo<T>::operator=(Foo<T> const&) 
M::operator=(M const&) 
=== 

따라서, 귀하의 예제에서, p = foo();는 호출하지 않는 사용자 정의 template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs)하지만, 소스를 공개하지 않고 pointee 회원을 간단하게 할당하는 암시 적으로 생성 된 버전입니다.

+0

그게 열쇠 야! – mi2think