2011-02-11 7 views
1

:는 괜찮 객체가 삭제 소유자에게하기가 그것을 나는이 같은 다소있는 시나리오가

class Owner { 
public: 
    enum Type {TypeB, TypeC}; 
    void swap(Type type); 
private: 
    A* m_a; 
}; 

class A { 
}; 

class B : public A { 
    void foo(); 
    Owner* m_owner; 
}; 

class C : public A { 
    void bar(); 
    Owner* m_owner; 
}; 

void Owner::swap(Type type) { 
    if (type == TypeC) { 
    delete m_a; 
    m_a = new C(); 
    } else if (type == TypeB) { 
    delete m_a; 
    m_a = new B(); 
    } 
} 

void B::foo() { 
    m_owner->swap(TypeC); 
    // will be deleted after this!! 
} 

기본 A 형의 객체에 대한 포인터를 가지고있는 소유자 클래스가있다 유형 B는 소유자에 대한 역 포인터를가집니다. 이 객체가 소유자에게 다른 A 유형으로 바꿔달라고 요청하는 시나리오가 있습니다. C.

B :: foo가 소유자에게 삭제하는 것이 안전할까요? Owner :: swap()에 대한 호출 후에 아무 것도하지 않으면 충돌이 발생합니다. 그것은 마치 "이것을 삭제하십시오"시나리오와 같습니다.

+2

'new C()'를 호출하기 전에'delete on m_a'를 호출하지 마십시오. 이것은 예외가 아닙니다. 새로운 작업이 실패하면 스택이 풀리고 잠재적으로 Owner의 소멸자에서 이중 삭제로 이어집니다 (간결함을 위해 생략 한 것으로 가정). 새로운/스왑/삭제 또는 바람직하게는 스마트 포인터를 사용하십시오. –

+1

'Owner :: swap (Type type)'에서,'delete m_b;'행은'Owner'에 멤버 m_b가 없으므로'delete m_a;'이어야합니다. –

+0

그 문제는 해결되었습니다. –

답변

2

A의 소멸자를 virtual으로 정의하면 완벽하게 괜찮습니다. 나는, 어떤 개체가 여기 삭제됩니다 swap 함수를 호출하는 일을 궁금

else if (type == TypeB) { 
    delete m_a; //not m_b, as Owner doesn't have any member named `m_b`. 
    m_a = new B(); 
    } 

그러나 : 그런데

, 당신의 코드는 작은 수정을 필요로? 그렇다면 클래스에 디자인 문제가 있으며 그 이후에 프로그램이 중단 될 수 있다고 말하고 싶습니다.

+0

디자인 문제가 있습니다. 그러나 이것은 내가 가지고있는 가장 고통스러운 옵션입니다. 그래서 내가 미치는지 아닌지 알고 싶었습니다. –

+0

10k를 치는 것에 축하해! 지난 번에 내가 너를 확인했다. :) –

1

스왑을 호출 한 후 클래스의 필드에 액세스하려고하면 충돌이 발생하지만 충돌은 발생하지 않지만 메모리 손상 시나리오가 시작됩니다.

말인지 모두는 다음과 같습니다

void B::foo() { 
    //this valid 
    m_owner->swap(TypeC); 
    //this invalid 
} 
+0

왜? 필드에 유효한 새 값이 다시 할당됩니다. 문제는이 메서드가 스레드로부터 안전하지 않다는 것입니다. –

+0

"this"의 주소가이 함수 중에 변경되지 않기 때문에 owner-> swap에 대한 호출 아래에서이 포인터는 여전히 동일합니다. –

+0

완전히 스레드 안전하지는 않습니다. 한 번에 하나의 쓰레드 만 주어진'Owner '에 접근하는 한,'operator new'와'operator delete'가 쓰레드에 안전하다면 쓰레드에 안전 할 수 있습니다. 또는 객체를 보호하기 위해 외부 뮤텍스를 추가 할 수 있습니다. 'std :: string'의 일부 구현의 copy-on-write 동작과 비교하고 비교해보십시오. 여기서 스레드에 대한 문자열의 비공개 사본을 만든 것으로 생각합니다. 스레드가 문자열을 변경할 때 죽는 것을 알아낼뿐입니다. 모든 문자열 연산을 포괄하는 전역 뮤텍스를 만들지 않는 한. –

1

그것은 확인 개체 소유자가 같은 당신이 더 이상 사용하지 않는 개체를 삭제하는 말. 자살을위한 물건 (delete this)도 괜찮습니다.이 표준은 어떠한 경우에도 도덕적 판단을하지 않습니다.

관련 문제