2010-01-17 3 views
6

C/C++로 코딩하는 동안 오랜 시간이 걸렸습니다. 지금은 제가하고있는 프로젝트에서 효율성이 필요합니다.C++ Boost shared_ptr을 사용하여 메모리 관리를 신경 쓰지 않고 Java 코딩으로 프로그래밍 할 수 있습니까?

이 shared_ptr에서 이해할 수있는 것은 내가 필요할 때 기본적으로 개체를 삭제한다는 것입니다. 예를 들어, 내 객체에 shared_ptr의 벡터가 있다면, 벡터를 반복하고 소멸자의 각 요소를 삭제하는 것에 대해 걱정할 필요가 없을 것입니다. 다시 말해서, 내가 이것을 사용하는 한 메모리 관리에 대해 걱정할 필요가 없다는 것입니다. 아니면 나는 이것을 완전히 오해하고 있는가? 그것은 너무 좋게 사실로 들립니다.

+0

정말 좋아하는 소리는 boost :: ptr_vector입니다. 벡터는 포인터의 소유권을 가져 와서 덮어 쓰거나 벡터가 소멸되면 포인터를 삭제합니다. –

+3

Java처럼 코드를 작성하면 "C++의 효율성"을 얻을 수 있다고 생각합니까? 마법은 없습니다. 프로그램이 C++로 작성 되었기 때문에 프로그램이 빠르지 않습니다. 그것은 효율적이기 위해 작성 되었기 때문에 빠릅니다. C++이 자바 인 것처럼 보이는 것은 유지 보수성과 성능면에서 최악의 경우를 제공합니다. – jalf

답변

11

공유 포인터는 참조 카운트를 사용하여 구현된다는 것을 알아야합니다. 즉, 포인터 그래프에 사이클이 있으면 오브젝트가 해제되지 않는다는 것을 의미합니다. 즉, b 및 b에 대한 점이 a를 가리키고 a 또는 b를 가리 키지 않으면 a 및 b 둘 다 참조 횟수가 '1'이므로 해고되지 않습니다.

부스트는이 문제를 해결할 수있는 약한 포인터를 제공하므로 참조 횟수를 증가시키지 않고 공유 객체에 대한 포인터를 저장할 수 있습니다. 약한 포인터는 공유 포인터가 해제 된 후 포인터를 역 참조하려고 시도 할 때 프로그램의 충돌을 일으키지 않고 예외를 발생시키는 안전 레이어를 제공합니다.

공유 포인터도 성능 측면에서 상당히 비쌉니다 (적어도 원시 포인터와 비교할 때).하지만 포인터를 사용하고 어디서나 프로파일 러가 병목 현상을 식별하면 제거하는 것이 좋습니다.

그렇지만 동적 할당 객체를 관리하는 데 매우 유용합니다.

편집 : 또 다른 잡았다 (즉,이 부스트 페이지에 언급 한 것) "일시적으로"shared_pointers을 방지하는 것입니다 : 컴파일러는

tmp1 = new B; 
tmp2 = A(); 
tmp3 = boost::shared_ptr<B>(tmp1) 
func(tmp2,tmp3) 

으로이를 최적화 할 수있다

func(A(), boost::shared_ptr<B>(new B)); 

때문에 보일 수있는 언뜻보기에 괜찮 았지만 A()가 예외를 발생시킨 다음 B가 할당되었지만 shared_ptr이 아직 그것을 확보하지 못해 포인터가 해제되지 않습니다.

+0

+1 순환 참조를 언급합니다. 또한 예외 안전 코드 작성이 쉽다는 것을 잊지 마십시오. – AraK

+0

기술적으로 정답이지만, 이런 식으로 코딩 할 때 C++를 사용하는 OP의 동기였던 효율성을 잃어 버리게됩니다. – jalf

+0

그러나 그렇다면 항상 중요한 코드에서 문제를 일으키는 공유 포인터를 최적화 할 수 있습니다. 다른 방식보다 주변에서 그렇게하는 것이 훨씬 낫습니다. –

6

이렇게 할 수는 있지만 일반적으로 좋지 않습니다. 처음에는 당신이 얻을 수있는 효율성의 일부 또는 전부를 잃을 수도 있습니다.

더 중요한 것은 코드 설계를 피하려고하는 것 같습니다. Java에는 gc가 있으므로 메모리 관리에 대해 걱정할 필요는 없지만 객체 수명에 대해서는 여전히 염려해야합니다. 혼란스런 디자인으로 끝내기 쉬운 사람이 누구인지에 대해 분명하지 않은 경우.

C++은 객체 수명과 관련하여 많은 옵션을 제공합니다. 모든 복잡한 객체를 힙에 할당해야하는 것은 아닙니다. shared_ptr은 공유 소유권이 필요한 개체 (이름에서 알 수 있듯이)에 사용해야하지만 이는 긍정적 인 디자인 결정이어야합니다. 공유 또는 양도 할 수있는 소유권이 필요하지 않은 경우 오브젝트를 소유하는 더 나은 방법이 있습니다.

4

여기 Is there a boost::shared_ptr<T> equivalent in C#? 다른 자동 메모리 관리 전략에 대한 정보를 게시했습니다. GC와 참조 카운팅의 주요 차이점을 설명합니다.

현대의 C++ 개발자 중 일부만 수동 메모리 (또는 리소스) 관리와 같은 것을 사용합니다. 우리 대부분은 대신 RAII 관용구를 사용합니다 (http://en.wikipedia.org/wiki/RAII 참조).자원을 다루는 데 도움이되는 몇 가지 유틸리티 클래스.

Shared_ptr - 일상적인 메모리/리소스 관리 작업을 용이하게하는 훌륭한 기술입니다. 이 기법에는 순환 구조를 처리 할 수없는 단점이 있으며 시간과 공간 모두에서 성능 오버 헤드가 있습니다. 참조에 대한 모든 연산에 대해 구현시 이제 산술 연산이 수행되고 분리 케이스에서는 조건부 명령어가 실행됩니다. 또한 모든 개체는 개수를 보유 할 추가 필드로 확장해야합니다.

최근에 꽤 큰 프로젝트에 참여했습니다. (내 부분에는 200 개가 넘는 클래스가 포함되어 있습니다.) 절대 수동으로 연산자 삭제를 사용하지 않습니다. 이러한 유틸리티는 코딩, 디버깅, 유지 보수를 용이하게하며 개발 비용을 현저하게 줄입니다. 최근에 유사한 프로젝트 (매우 유사한 비즈니스 로직 및 아키텍처)에 참여했지만 C#에 참여했습니다. 그리고 나는 진정으로 당신에게 말할 수 있습니다. 그들은 C++ 프로젝트의 자동 메모리 관리가 무엇보다도 비슷합니다.

P. 모든 C++ 프로그래머가 알고있는 것은 아니지만 shared_ptr은 사용자 정의 삭제자를 사용하여 자동 메모리 관리 (자동 메모리 관리는 물론)에서 사용할 수 있습니다.

+0

+1 사용자 정의 deleter입니다. C API에서 오는 리소스에 대해 RAII를 구현할 때 유용합니다. 기능을 거의 부스트하지 마십시오. –

관련 문제