2016-07-14 2 views
1

링크 목록의 개념을 사용하여 List 클래스를 만들려고합니다. 원래 C++ 표준 new 키워드를 사용하는 동안 C++ 11 std::shared_ptr에 대한 전환을 결정했습니다. . 그러나 스마트 포인터를 사용할 때 충돌이 발생할 때 제대로 작동하지 못합니다.C++ 설정 포인터 shared_ptr과 동일

class List 
{ 
public: 
    void push_back(...) { 
     Node *temp = new Node; 
     ... 
     if (!head) { 
      head = temp; 
      return; 
     } 
     else { 
      Node *last = head; 
      ... 
      last->next = temp; 
     } 
    } 
    ... 

private: 
    Node *head = nullptr; 
}; 

그리고 여기가 변화의 모습입니다 : 여기에 코드의 일부 비트는 변경 전에있는 문제가 headlast가 동적으로 할당되지 않습니다 수 있습니다처럼

class List 
{ 
public: 
    void push_back(...) { 
     std::shared_ptr<Node> temp(new Node); 
     ... 
     if (!head) { 
      head = temp.get(); 
      return; 
     } 
     else { 
      Node *last = head; 
      ... 
      last->next = temp.get(); 
     } 
    } 
    ... 

private: 
    Node *head = nullptr; // don't need this to be a smart ptr 
}; 

내 기분이 그리고 아마도 그들은 shared_ptr으로 일해야 할 필요가 있을지 모르겠지만 확실하지 않습니다. 정확하게 내가 뭘 잘못하고 어떻게 해결할 수 있습니까? 내 문제를 해결할 수있는 것을 찾을 수 없기 때문에 이것이 중복되지 않기를 바란다. 감사.

편집 : 다음은 Node 구조체의 :

struct Node{ 
    int data; 
    Node* next; 
}; 
+0

, 내가 문제가 가능성이 Node' '의 정의는 추측에는 요 – Assimilater

+0

그럼 내가 동적으로 할당하거나 다른 프로그램이 작동하지 않습니다'temp' 노드를 필요 것 같아, 난 그냥했다 표준'new'가 아닌'shared_ptr'을 동적으로 할당하는 것을 고려하십시오. 그리고 도움이된다면'Node' 구조체를 게시 할 수 있습니다. –

+0

예,'Node' 구조체를 게시하십시오. – Assimilater

답변

1

귀하의 주요 문제는 당신이 모든 방법을 사용하는 shared_ptr을 가장 사용하려고하는 경우이다. next을 원시 번호 대신 shared_ptr으로 만드십시오. std::shared_ptr은 후드 아래에 무엇을

struct Node { 
    int data; 
    std::shared_ptr<Node> next; 
} 

포인터에 얼마나 많은 참조 카운트를 유지한다. 복사 생성자를 사용하거나을 사용하면 참조 횟수가 늘어납니다. 인스턴스가 범위 밖으로 벗어나 소멸자가 호출되면 (또는 operator=과 다른 포인터를 지정하면) 참조 횟수가 감소합니다. 카운트가 0이면 포인터가 파괴됩니다.

// pass by value invokes copy constructor (refcount + 1) 
void myFunc(std::shared_ptr<MyClass> var) { 

    // Code using var 

} // end of function invokes destructor (refcount - 1) 

void run() { 
    std::shared_ptr<MyClass> ptr(new MyClass); // refcount = 1 
    myFunc(ptr); // refcount = 2 
    // After myFunc returns refcount = 1 

} 
int main() { 
    run(); // refcount = 1 
    // After run returns, refcount = 0 and the pointer is deleted 
} 

get()를 사용하여 상관없이 그 포인터가 주위 여부, 어떤 점에서 삭제 될 수 있습니다 메모리에 대한 포인터를 소개합니다. 원시 포인터가 shared_ptr이 삭제 된 메모리를 가리키고 있기 때문에 segfaults가 발생할 수 있습니다.

get()은 참조 횟수에 영향을주지 않기 때문입니다. 어떻게 그럴 수 있니? 더 이상 shared_ptr이 아니므로 클래스 정의가 사용자가 수행 한 작업을 알 수 없거나 삭제 될 수 없습니다. get()이 참조 횟수를 증가 시키면 이후에 감소시킬 것이 없으며 메모리는 절대로 공개되지 않습니다. 그건 메모리 누출이야! 처음에 std::shared_ptr을 가지고

+0

아, 알겠습니다. 나는 모든 포인터를 스마트 포인터 (반드시 동적으로 할당 된 것과 같지 않음)로 대체했으며, 문제가 해결되었다. 감사. –

+0

사실,이 질문에 의해 촉발, 나는 그들이 또한 링크 된 목록 * 자체 * (아이러니를 사랑 해요)로 구현할 수 있습니다 오늘 배웠습니다. 참조 : http://stackoverflow.com/questions/725142/how-does-a-reference-counting-smart-pointers-reference-counting-work – Assimilater

+0

하는 이봐, 꽤 좋은! –

4

이유는 std::shared_ptr 포인터의 완전하고 전체 소유권을 가지고 있고,이 포인터에 대한 마지막 참조가 사라질 일단 deletestd::shared_ptr의 책임을 확인하는 것입니다. 그게 std::shared_ptr입니다.

이것은 일단 포인터가 std::shared_ptr에 배치되면 std::shared_ptr이 포인터 관리에 대한 완전한 책임을진다는 것을 의미합니다. 그것은 그것을 완전히 소유하고 있습니다.

그러므로 포인터를 std::shared_ptr에 삽입하는 것은 의미가 없습니다.다음 바로 꺼내 :

head = temp.get(); 

get() 기능이 존재하는 이유가있다, 그러나 이것은 그들 중 하나가 아닙니다.

std::shared_ptr을 올바로 사용하려면 모든 것이 std::shared_ptr이어야합니다. headstd::shared_ptr 할 필요가 :

std::shared_ptr<Node> head; // yes, it does need to be a smart ptr 

왜이 std::shared_ptr해야합니까? 이 temp 스마트 포인터가 파괴됩니다

특히
std::shared_ptr<Node> temp(new Node); 

, 때이 함수가 반환 : 그렇지 않은 경우에 그래서, 당신은 이런 일이 벌어 질 것 어떻게 생각하세요? 음,이 Node을 참조한 것은 마지막 std::shared_ptr이 될 것이므로, 행복하게 delete이됩니다. 사실은 get() 일찍, head에 두는 것은 중요하지 않습니다. 이제 노드 delete을 가리키는 head이 있습니다. Hilarity가 계속됩니다. 모든 것이 std::shared_ptr해야하는 이유

는 그리고이입니다. head뿐만 아니라 Nodenext 구성원 std::shared_ptr이어야합니다.

이제 순환 참조를 포함하는 함정이 std::shared_ptr 그림을 입력 할 때, 그 놀이에 온다. 그러나 그것은 다른 질문이 될 것입니다. 언뜻

+0

대단히 상세한 답변을 해주셔서 감사합니다. 그의 주먹 와서 문제를 해결로 나는 Assimilater의 응답을 적용하기로 결정했습니다,하지만 난 정말 답 :이 답변은 :) 등장하면서 나는 정보의 이런 종류의 내 대답을 편집 한 –

+0

@ArchieGertsman을 좋아합니다. 두포에서 진행되는 작업을 조금 더 이해하는 데 도움이 될 수 있습니다. – Assimilater