문제

대학에서 항상 사용하지 않은 개체를 해제해야하지만 실제로하는 방법이 아니라는 것을 배웠습니다.예를 들어 코드를 올바르게 구성하는 등. C ++에서 포인터를 처리하는 방법에 대한 일반적인 규칙이 있습니까?

현재 부스트를 사용할 수 없습니다.내가 사용하는 프레임 워크가 제네릭 사용을 금지하기 때문에 순수 C ++를 고수해야합니다.

도움이 되었습니까?

해결책

저는 전적으로 개발자 규칙을 기반으로 한 뛰어난 시스템을 갖춘 임베디드 Symbian OS로 작업했습니다.

  1. 하나의 개체 만 포인터를 소유합니다.기본적으로 제작자입니다.
  2. 소유권을 양도 할 수 있습니다.소유권 전달을 나타 내기 위해 객체는 메소드 서명의 포인터로 전달됩니다 (예 : void Foo (Bar * zonk);).
  3. 소유자가 개체를 삭제할시기를 결정합니다.
  4. 사용하기 위해 메서드에 객체를 전달하기 위해 객체는 메서드 서명에서 참조로 전달됩니다 (예 : void Foo (Bat & zonk);).
  5. 비 소유자 클래스는 소유자가 사용 중에 그것을 파괴하지 않을 것이라고 확신 할 수있을 때만 주어진 객체에 대한 참조 (포인터가 아님)를 저장할 수 있습니다.

    기본적으로 클래스가 단순히 무언가를 사용하는 경우 참조를 사용합니다.클래스가 무언가를 소유하고 있다면 포인터를 사용합니다.

    이는 아름답게 작동했으며 사용하는 것이 즐거웠습니다.메모리 문제는 매우 드뭅니다.

다른 팁

규칙 :

  1. 가능하면 스마트 포인터 .부스트에는 좋은 것 .
  2. 스마트 포인터를 사용할 수 없습니다. null out 삭제 후 포인터 .
  3. 규칙 1을 사용할 수없는 곳에서는 절대 작업하지 마십시오.

    누군가 규칙 1을 허용하지 않는 경우, 다른 사람의 코드를 잡고 변수 이름을 변경하고 저작권 고지를 삭제하면 아무도 알아 차리지 못할 것임을 기억하십시오.학교 프로젝트가 아니라면 그들은 꽤 정교한 도구로 그런 종류의 헛소리를 실제로 확인합니다.이 질문 도 참조하세요.

여기에 다른 규칙을 추가하겠습니다.

  • 자동 개체가 잘 작동하는 경우 개체를 새로 만들거나 삭제하지 마세요.

    우리는 C ++를 처음 접하는 프로그래머 나 Java와 같은 언어를 사용하는 프로그래머가 새로운 것을 배우고 컨텍스트에 관계없이 객체를 만들고 싶을 때마다 집착 적으로 사용하는 것처럼 보입니다. 이것은 순전히 유용한 일을하기 위해 함수 내에서 객체가 로컬로 생성 될 때 특히 위험합니다. 이런 식으로 new를 사용하면 성능에 해를 끼칠 수 있으며 해당 삭제를 잊어 버렸을 때 어리석은 메모리 누수를 너무 쉽게 만들 수 있습니다. 예, 스마트 포인터는 후자에 도움이 될 수 있지만 성능 문제를 해결하지는 못합니다 (신규 / 삭제 또는 이와 동등한 기능이 배후에서 사용된다고 가정). 흥미롭게도 (아마도) Visual C ++를 사용할 때 삭제가 새 것보다 더 많은 비용이 드는 경향이 있다는 것을 발견했습니다.

    이 혼동 중 일부는 호출하는 함수가 포인터 또는 스마트 포인터를 인수로 사용할 수 있다는 사실에서 비롯됩니다 (참조가 더 좋고 / 명확 할 때). 이것은 포인터를 함수에 전달할 수 있도록 포인터를 "생성"해야한다고 생각하게합니다 (많은 사람들이 이것이 새로운 기능이라고 생각하는 것 같습니다). 분명히 이것은 함수 프로토 타입과 함께 제공되는 명확한 주석으로 강화되는 호출 규칙을 가능한 한 명확하게 만들기 위해 API를 작성하는 방법에 대한 몇 가지 규칙이 필요합니다.

일반적인 경우 (자원이 반드시 메모리가 아닌 자원 관리)의 경우 RAII 패턴 .이것은 C ++ 개발자에게 가장 중요한 정보 중 하나입니다.

일반적으로 꼭 필요한 경우가 아니면 힙에서 할당하지 마세요. 필요한 경우 수명이 길고 코드의 다양한 부분간에 공유해야하는 개체에 대한 참조 계산을 사용합니다.

때때로 개체를 동적으로 할당해야하지만 특정 시간 동안 만 사용됩니다. 예를 들어, 이전 프로젝트에서 저는 데이터베이스 스키마의 복잡한 메모리 내 표현을 만들어야했습니다. 기본적으로 객체의 복잡한 순환 그래프입니다. 그러나 그래프는 데이터베이스 연결 기간 동안 만 필요했으며 그 후에 모든 노드를 한 번에 해제 할 수있었습니다. 이런 종류의 시나리오에서 사용하기에 좋은 패턴은 "로컬 GC 관용구"라고 부르는 것입니다. 내 자신의 코드와 Cocoa에서만 본 것이므로 "공식적인"이름이 있는지 확실하지 않습니다 ( NSAutoreleasePool (Apple Cocoa 참조)).

간단히 말해 new를 사용하여 할당 한 임시 개체에 대한 포인터를 유지하는 "수집기"개체를 만듭니다. 일반적으로 정적 범위 (예 : RAII 관용구를 구현하는 스택 할당 객체) 또는 동적 범위 (예 : 데이터베이스 연결의 수명에 연결됨)와 같은 프로그램의 일부 범위에 연결됩니다. 내 이전 프로젝트). "collector"객체가 해제되면 해당 소멸자는 자신이 가리키는 모든 객체를 해제합니다.

또한 DrPizza와 마찬가지로 템플릿을 사용하지 않는 제한이 너무 가혹하다고 생각합니다. 그러나 고대 버전의 Solaris, AIX 및 HP-UX에서 많은 개발을 수행 한 후 (최근-예, 이러한 플랫폼은 Fortune 50에도 여전히 적용됨) 이식성에 대해 정말로 관심이 있다면 템플릿을 가능한 한 적게 사용해야합니다. 컨테이너와 스마트 포인터에 사용하는 것은 괜찮을 것입니다 (저에게 효과적이었습니다). 템플릿이 없으면 내가 설명한 기술을 구현하기가 더 어렵습니다. "컬렉터"가 관리하는 모든 개체는 공통 기본 클래스에서 파생되어야합니다.

G'day,

Scott Meyers의 "Effective C ++"관련 섹션을 읽어 보는 것이 좋습니다.읽기 쉽고 그는 방심 함을 가두기위한 몇 가지 흥미로운 점을 다루고 있습니다.

템플릿이 부족하다는 점도 흥미 롭습니다.따라서 STL 또는 Boost가 없습니다.와우.

BTW 사람들이 대회에 동의하도록하는 것은 훌륭한 아이디어입니다.모든 사람이 OOD에 대한 규칙에 동의하도록하는 것입니다.BTW Effective C ++의 최신 버전에는 첫 번째 버전이 가졌던 OOD 규칙에 대한 훌륭한 장이 없습니다.공개 가상 상속과 같은 규칙은 항상 "isa"관계를 모델링합니다.

  • 메모리 관리를 사용해야하는 경우 수동으로 delete를 호출했는지 확인하십시오. 같은 범위 / 기능 / 클래스 / 모듈, 먼저 적용됩니다. 예 :
  • 함수 호출자가 함수로 채워진 메모리를 할당하도록하고, 새로운 포인터를 반환하지 않습니다.
  • 새로 호출 한 것과 동일한 exe / dll에서 항상 delete를 호출합니다. 그렇지 않으면 힙 손상 (다른 호환되지 않는 런타임 라이브러리) 문제가 발생할 수 있기 때문입니다.

기능과 같은 스마트 포인터를 구현하는 일부 기본 클래스에서 모든 것을 파생시킬 수 있습니다 (ref () / unref () 메서드 및 카운터 사용).

@Timbo가 강조한 모든 포인트는 기본 클래스를 디자인 할 때 중요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top