2009-03-25 3 views
3
문장은 아래입니다

, 브루스 에켈 (Bruce Eckel)에 의해 The Positive Legacy of C++ and Java, C++에서 연산자 오버로딩에 대해 :메모리 할당으로 연산자 오버로딩이 필요합니까?

C++ 모두 스택 할당과 힙 할당을 가지고 있으며, 모든 상황과 을하지 처리하도록 연산자를 오버로드합니다 메모리 누수가 발생합니다. 어려운 참으로.

나는 연산자 오버로딩이 메모리 할당과 어떤 관련이 있는지 이해하지 못합니다. 아무도 상관 관계를 설명 할 수 있습니까?

+0

저는 C++로 작업하지 않았습니다. 그러나 연산자를 오버로드하면 새 값을 반환해야 할 수 있습니다 (간단한 값의 경우 스택에, 복잡한 유형의 경우에는 힙에 포함될 수 있음). 사람 * a; 사람 * b; 사람 * c = a + b; – shahkalpesh

답변

3

:

첫째, newdelete ++ C 모두 실제로 사업자이다; 이러한 연산자를 오버로드하여 개체에 대한 사용자 지정 할당 동작을 제공하려는 경우 누출을 방지하기 위해 매우주의해야합니다.

둘째, 일부 유형의 개체는 메모리 관리 버그를 피하기 위해 을 오버로드해야합니다. 예를 들어, 스마트 포인터 객체 (Boost shared_ptr와 같은)를 계산하는 참조가있는 경우 operator=을 구현해야하며 올바르게 수행해야합니다. 이 부러진 예제를 생각해 봅시다 :

template <class T> 
class RefCountedPtr { 
public: 
    RefCountedPtr(T *data) : mData(data) { mData->incrRefCount(); } 
    ~RefCountedPtr() { mData->decrRefCount(); } 
    RefCountedPtr<T>& operator=(const RefCountedPtr<T>& other) { 
     mData = other.mData; 
     return *this; 
    } 
    ... 
protected: 
    T *mData; 
}; 

mDataother.mData에 참조 카운트를 관리하지 않기 때문에 여기 깨지는 operator= 구현 : 그것은 누출로 이어지는 mData에 참조 카운트를 감소하지 않는다; 참조 카운트를 other.mData으로 증가시키지 않습니다. 실제 참조가 모두 사라지기 전에 가리킨 객체를 삭제할 수 있기 때문에 메모리 오류가 발생할 수 있습니다.

클래스에 대해 자신의 operator=을 명시 적으로 선언하지 않으면 컴파일러에서 여기에 표시된 구현과 동일한 동작을하는 기본 구현을 제공한다는 점에 유의하십시오. 즉,이 특정 사례에서 완전히 깨졌습니다.

기사에서 말하는 것처럼 어떤 경우에는 연산자를 오버로드해야하며 모든 상황을 올바르게 처리해야합니다.

EDIT : 죄송합니다. 참고 문헌이 책이 아닌 온라인 기사라는 것을 알지 못했습니다. 전체 기사를 읽은 후에도 의도 한 바가 명확하지 않지만 Eckel은 아마 위에서 설명한 두 번째 상황과 관련 있다고 생각합니다.

+0

그 기사는 ... 단지 링크를 클릭하십시오 – yesraaj

+0

기사는 실제로 많은 문맥을 제공하지 못했습니다 - 나는 에릭이 기사에서 언급 된 책에 대해 이야기하고 있다고 의심합니다. –

0

연산자는 함수입니다. 구문형 설탕을 추가했기 때문에 기억에 조심할 필요가 없다는 의미는 아닙니다. 다른 멤버/글로벌/친구 기능과 마찬가지로 메모리를 관리해야합니다.

래퍼 포인터 클래스를 구현할 때 오버로드 할 때 특히 중요합니다.

operator+ 또는 operator+=을 오버로드하여 문자열 연결이 있습니다. 자세한 내용은 basic_string 템플릿을 참조하십시오.

내가 몇 가능한 해석을 상상할 수
1

사실 새로운 C++의 연산자는 사용자 정의 된 메모리 관리 기능을 제공하기 위해 재정의 할 수 있습니다.example 여기를보세요.

0

Java와 C++ 사이의 연산자 오버로드를 비교할 경우 newdelete에 대해 언급하지 않을 것입니다. Java는 새로운 메모리 관리 세부 정보를 충분히 제공하지 않으며 삭제할 필요가 없습니다.

포인터 유형에 대해 다른 연산자를 오버로드 할 수 없습니다. 하나 이상의 인수는 클래스 또는 열거 형이어야하며 포인터에 대해 다른 연산자를 제공 할 수는 없습니다.

C++의 연산자는 값 또는 값에 대한 const 참조에서 작동합니다.

값에 대한 연산자 또는 값에 대한 const 참조가 값 이외의 값을 반환하는 것은 매우 드문 경우입니다.

모든 C++ 함수에 공통적으로 나타나는 명백한 오류 - 메모리 누수와 반대되는 스택 할당 객체에 대한 참조를 반환하거나 값이 아닌 new으로 만든 객체에 대한 참조를 반환합니다. 일반적으로 배운 적이없는 직업에서 한 번만 끝난 경우), 일반 운영자가 메모리 문제가있는 시나리오를 찾기가 어려울 수 있습니다.

따라서 피연산자가 정상적인 사용 패턴에 따라 스택 또는 힙 할당 여부에 따라 여러 버전을 만들 필요가 없습니다.

연산자에 대한 인수는 값 또는 참조로 전달 된 개체입니다. C++에는 객체가 힙이나 스택에 할당되었는지 테스트 할 수있는 이식 메커니즘이 없습니다. 개체가 값으로 전달 된 경우 항상 스택에 저장됩니다. 따라서 두 가지 경우에 대해 연산자의 동작을 변경해야한다면 C++에서 이식 할 수 없습니다. (많은 OS에서 객체에 대한 포인터가 일반적으로 스택에 사용되는 공간에 있는지 또는 힙에 일반적으로 사용되는 공간에 있는지 테스트 할 수 있지만 이식성이없고 신뢰할 수 없습니다.) (또한 운영자 두 개의 포인터를 인수로 취한 객체가 포인터라고 그냥 힙이 할당되어 있다고 믿을만한 이유가 없습니다. 그 정보는 단순히 C++에 존재하지 않습니다.)

유일한 중복은 연산자 [ ] 여기서 동일한 연산자는 접근 자 및 변형 자 둘 다로 사용됩니다. 그런 다음 const 및 non-const 버전을 갖는 것이 일반적이므로 수신기가 const가 아닌 경우 값을 설정할 수 있습니다. 그것은 좋은 것입니다 - 상수로 표시된 객체 (공개적으로 액세스 할 수있는 상태)를 변경할 수없는 것입니다.

관련 문제