2010-12-31 8 views
5

누군가 C++ 프로그래머에게 Java (및 C#뿐만 아니라) 참조와 shared_ptr (Boost 또는 C++ 0x에서) 간의 가장 중요한 차이점을 설명 할 수 있습니까?shared_ptr과 관리되는 언어 참조의 비교

나는 shared_ptr이 어떻게 구현되는지 더 잘 알지 못합니다. 다음과 같은 차이점에 대해 궁금합니다.

1) 성능. 2) 사이클링. shared_ptr은 순환 될 수 있습니다 (A와 B는 서로 포인터를 유지합니다). 자바에서 사이클링이 가능합니까? 3) 다른 건 없나요?

감사합니다.

답변

4

성능 : shared_ptr 꽤 잘 수행되지만 내 경험상 명시 적 메모리 관리보다 효율적이지 않습니다. 주로 참조 수가 계산되고 참조 횟수도 할당되어야하기 때문입니다. 얼마나 잘 수행되는지는 많은 요소에 따라 다르며 Java/C# 가비지 수집기와 얼마나 잘 비교되는지는 유스 케이스별로 결정될 수 있습니다 (다른 요소들 사이의 언어 구현에 따라 다름).

사이클weak_ptr으로 만 가능하고 두 개가 아닌 shared_ptr입니다. Java는 더 이상 부담없이 사이클링을 허용합니다. 가비지 컬렉터는 break the cycles입니다. 내 생각 엔 C#도 똑같이한다는 것입니다.

: shared_ptr이 가리키는 객체는 마지막 참조가 범위를 벗어나 자마자 파괴됩니다. 소멸자는 즉시 호출됩니다. 자바에서는 finalizer가 즉시 호출되지 않을 수 있습니다. C#이이 시점에서 어떻게 작동하는지 모르겠습니다.

+3

성능에 대한주의 사항,'make_shared' (http://www.boost.org/doc/libs/release/libs/smart_ptr/make_shared.html)가 사용되면 레퍼런스 카운트와 참조 된 객체 모두가 하나의 블록에 할당됩니다 . – dalle

+1

아마도 shared_ptr의 가장 큰 성능은 ref 카운터의 인터록 증가/감소입니다. – sbk

+0

@sbk : 왜 이것이 성능에 영향을 미쳤다고 생각합니까? 일반적으로 단일 어셈블리 명령어로 구현됩니다 (암시 적으로이를 지원하는 하드웨어에 대한 잠금이 필요 없음). –

3

주요 차이점은 공유 포인터의 사용 횟수가 0이되면 포인터가 가리키는 객체가 파괴된다는 것입니다 (소멸자가 호출되고 객체가 할당 해제 됨). Java 및 C#에서 가비지 수집기가 객체의 할당을 취소 할 때까지 (즉, 결정적이지 않은 경우) 객체의 할당 해제가 연기됩니다.

주기에 관해서, 나는 당신이 의미하는 바를 잘 모르겠다. Java와 C#에서는 서로를 참조하는 멤버 필드를 포함하는 두 개의 객체를 가지므로주기를 생성하는 것이 일반적입니다. 예를 들어 자동차와 엔진 - 자동차는 엔진 필드를 통해 엔진을 말하며 엔진은 자동차 필드를 통해 자동차를 참조 할 수 있습니다.

+1

C# 및 Java에는 "정상적인"소멸자가 없으며 해당 언어에서 잘못된 기능으로 간주되는 파일 확장자 만 있습니다. 소멸자와 쓰레기 수거는 확률이 떨어집니다. GC는 기본적으로 파괴 나 무한한 물체 수명을 의미합니다. –

+0

함수에서와 같이 소멸자의 개념과 소멸되는 개체의 소멸이라는 차이가 있습니다. 같은 용어가 두 이벤트에 모두 사용되므로 혼동을 일으킬 수 있다는 것을 알고 있습니다. 따라서 객체 할당 해제가 나중의 이벤트를 참조하는 단어를 선택하는 것이 좋습니다. –

+4

파괴는 할당 해제가 아니라 매우 다른 개념이므로 서로 바꾸어 사용할 수 없습니다. –

1

C++ 참조 카운트 포인터가있는 순환 참조는 삭제되지 않습니다. 약 포인터를 사용하여이 문제를 해결할 수 있습니다. Java 또는 C#의 순환 참조는 가비지 컬렉터가 이와 같이 느낄 때 삭제 될 수 있습니다.

C++ 참조 카운트 포인터의 수가 0으로 떨어지면 소멸자가 호출됩니다. 자바 객체가 더 이상 접근 가능하지 않으면, 파이널 라이저는 즉시 또는 항상 호출되지 않을 수 있습니다. 따라서 외부 리소스를 명시 적으로 처리해야하는 개체의 경우 명시 적 호출 형식이 필요합니다.

1

우선 Java/C#은 참조가 아닌 포인터 만 가지고 있습니다. 참조는 고유 한 C++ 기능입니다. Java/C#의 가비지 수집은 기본적으로 무한한 수명을 의미합니다. 반면에 shared_ptr은 카운트가 0이 될 때 공유 및 결정적 파괴를 제공합니다. 따라서 shared_ptr은 메모리 할당뿐만 아니라 모든 리소스를 자동으로 관리하는 데 사용할 수 있습니다. 어떤 의미에서 (어떤 RAII 디자인과 마찬가지로) 포인터 의미론을보다 강력한 가치 의미론으로 바꿉니다.

+4

"포인터"와 "참조"사이의 C++ 차이점은 해당 언어에만 있습니다. C#/Java 참조는 두 포인터 사이에 포인터 연산을 할 수 없기 때문에 둘 사이에 있습니다. –

+0

@larsmans, 그 의미는 자바가 의미 론적으로 포인터를 가지고있을뿐만 아니라 포인터 만 가지고 있다는 것입니다. 참조가 null이 아닌 것을 보증하는 참조 메커니즘이 부족합니다. 그러나 실제로는 포인터 연산이 없으며 피상적 인 구문 표기법이 일반적인 포인터 표기법이 아닙니다. –

+0

그러나 "참조"가 무엇인지에 대한 C++ 정의를 가정하기 때문에 여러분이 말하는 것은 잘못된 것입니다. Java는 참조라고하기 때문에 참조가 있습니다. 그들은 C++ 참조처럼 행동하지 않습니다. – jalf

1

아무도 관리 메모리의 메모리 관리자가 개체를 이동할 가능성을 지적하지 않았습니다.C#에는 간단한 참조/포인터가 없으며 관리자가 반환하는 객체를 설명하는 ID와 같이 작동합니다.
C++에서 shared_ptr을 사용하여 개체를 만든 후에 동일한 위치에 있기 때문에이 작업을 수행 할 수 없습니다.

관련 문제