2017-01-06 10 views
0

어떤 사람은이 패턴에 대한 질문을 게시하지만, 위의 예 만약에 내가 가지고있는 쿼리를 게시 내 마음에서 제기 된 문제의 해결책 ...혼란 ++

을 가지고 있지 모든 인스턴스는 s_prototypes 변수에 의해 초기화되고 다음 번에 그 객체가 복제 메소드의 새 객체로 대체되면 기존 객체는 어떻게됩니까 ?? 메모리 누수가 발생합니까 ??

지금까지 내가 예를 들어 두 개의 문 위의 이해 나에게

class Stooge { 
public: 
    virtual Stooge* clone() = 0; 
    virtual void slap_stick() = 0; 
}; 

class Factory { 
public: 
    static Stooge* make_stooge(int choice); 
private: 
    static Stooge* s_prototypes[4]; 
}; 

int main() { 
    vector roles; 
    int    choice; 

    while (true) { 
     cout << "Larry(1) Moe(2) Curly(3) Go(0): "; 
     cin >> choice; 
     if (choice == 0) 
     break; 
     roles.push_back(
     Factory::make_stooge(choice)); 
    } 

    for (int i=0; i < roles.size(); ++i) 
     roles[i]->slap_stick(); 
    for (int i=0; i < roles.size(); ++i) 
     delete roles[i]; 
} 

class Larry : public Stooge { 
public: 
    Stooge* clone() { return new Larry; } 
    void slap_stick() { 
     cout << "Larry: poke eyes\n"; } 
}; 
class Moe : public Stooge { 
public: 
    Stooge* clone() { return new Moe; } 
    void slap_stick() { 
     cout << "Moe: slap head\n"; } 
}; 
class Curly : public Stooge { 
public: 
    Stooge* clone() { return new Curly; } 
    void slap_stick() { 
     cout << "Curly: suffer abuse\n"; } 
}; 

Stooge* Factory::s_prototypes[] = { 
    0, new Larry, new Moe, new Curly 
}; 
Stooge* Factory::make_stooge(int choice) { 
    return s_prototypes[choice]->clone(); 
} 

Output 
Larry(1) Moe(2) Curly(3) Go(0): 2 
Larry(1) Moe(2) Curly(3) Go(0): 1 
Larry(1) Moe(2) Curly(3) Go(0): 3 
Larry(1) Moe(2) Curly(3) Go(0): 0 
Moe: slap head 
Larry: poke eyes 
Curly: suffer abuse 

을 혼동하지만 우리는 make_stooge 방법으로 clone 메소드를 호출 할 때 새로운 객체를 반환하고 기존 하나를 교체하는 경우는, 새로운 객체를 반환으로 다음 기존 개체가 여기에 메모리 누수를 만듭니다가

+0

- 즉 귀하의 게시 된 코드에서 일어나고 아니에요. –

답변

1

...

그래서이 일이 예 나를 혼란이다 .... (새 운영자가 완전히 별도의 객체를 생성하기 때문에 여기에 하나를 기존 반환하지 않음) n은이다. o 새로 생성 된 객체가 신중하게 vector (여기 roles)에 저장되기 때문에 코드에서 메모리 누수가 발생합니다.

프로그램이 종료되기 전에 그들은 그 벡터에서 사용하고, 파괴 :

... 
    for (int i=0; i < roles.size(); ++i) 
     delete roles[i]; 
} 

그러나 더 좋은 것 주요 종료 전에 return 0; ...

그리고을 작성하는 것이 좋습니다 파생시킬 클래스의 가상 소멸자 Larry 등의 간단한 소멸자가없는 경우 기본 클래스 포인터를 통해 삭제할 때 사용하지 않습니다.

class Stooge { 
public: 
    virtual Stooge* clone() = 0; 
    virtual void slap_stick() = 0; 
    virtual ~Stooge() {} 
}; 

정적 개체 인 s_prototypes의 경우 main이 호출되기 전에 프로그램 시작시 정적으로 초기화되며 수정되지 않습니다. 이들의 clone 메서드는 새 개체를 만들기 위해 호출되지만 s_prototype은 여전히 ​​이전 개체를 가리 킵니다. 새로 만든 개체를 저장하고 삭제하는 것이 중요한 이유입니다.

분명히 파괴되지 않기 때문에 실제로 4 가지 개체에 메모리 누수가 있습니다. 수명이 프로그램 종료까지 연장되어 모든 메모리가 해제 되었기 때문에 정적 오브젝트가 누출되는 것이 허용되는 것으로 종종 간주됩니다. 당신이 파괴 명시 할 경우

static Larry _larry; 
static Moe _moe; 
static Curly _curly; 
Stooge* Factory::s_prototypes[] = { 
    0, &_larry, &_moe, &_curly 
}; 

을 : 소멸자가 호출되는 것이 중요 경우, 당신은 또한 그들을 위해 정적 인스턴스를 생성한다

virtual ~Stooge() { 
     cout << "Delete " << this << endl; 
    } 

약간 프로그램의 끝을 변경 :

for (int i=0; i < roles.size(); ++i) 
     delete roles[i]; 
    cout << "END" << endl; 
    return 0; 
} 

출력 것 같은

... 
Delete 001ADB78 
END 
Delete 00F350A0 
Delete 00F3509C 
Delete 00F35098 

은 프로그램 종료 후에 정적 객체가 파괴되었음을 분명히 보여줍니다.

+0

질문은 결코 삭제되지 않는's_prototypes'의 포인터에 관한 것입니다. –

+0

네, 맞습니다. @DavidScarlett ... 하지만이 질문에 대한 해결책은 무엇입니까 ... –

+0

우리는이 메소드를 사용하여 복제 객체에서이 객체를 반환 할 수 있습니까? 프로토 타입 패턴 –

1

글쎄, 당신은 s_prototypes에있는 포인터가 절대로 삭제되지는 않지만, 적어도 이러한 객체는 프로그램의 전체 런타임 동안 지속될 것입니다. 따라서 해당 객체에서 수행해야 할 특정 작업이 없으면 소멸자라면 프로그램 종료 전에 삭제되지 않으면 세상 끝이 아닐 수 있습니다. 이것은 메모리가 지속적으로 누출 될 가능성이있는 코드만큼 나쁘지는 않으며 프로그램이 사용하는 메모리가 계속 증가 할 수 있습니다. 당신이 원하는 경우

,이 같은 대신 정적 인스턴스를 대체 할 수 :

그 새로운 객체를 반환 한 *을 기존으로 대체 * 경우
#include <iostream> 
#include <vector> 
using namespace std; 

class Stooge { 
public: 
    virtual Stooge* clone() = 0; 
    virtual void slap_stick() = 0; 
    virtual ~Stooge() = default; 
}; 

class Larry : public Stooge { 
public: 
    Stooge* clone() { return new Larry; } 
    void slap_stick() { 
     cout << "Larry: poke eyes\n"; } 
}; 
class Moe : public Stooge { 
public: 
    Stooge* clone() { return new Moe; } 
    void slap_stick() { 
     cout << "Moe: slap head\n"; } 
}; 
class Curly : public Stooge { 
public: 
    Stooge* clone() { return new Curly; } 
    void slap_stick() { 
     cout << "Curly: suffer abuse\n"; } 
}; 

class Factory { 
public: 
    static Stooge* make_stooge(int choice); 
private: 
    static Larry larry; 
    static Curly curly; 
    static Moe moe; 
}; 

int main() { 
    vector<Stooge*> roles; 
    int    choice; 

    while (true) { 
     cout << "Larry(1) Moe(2) Curly(3) Go(0): "; 
     cin >> choice; 
     if (choice == 0) 
     break; 
     roles.push_back(
     Factory::make_stooge(choice)); 
    } 

    for (int i=0; i < roles.size(); ++i) 
     roles[i]->slap_stick(); 
    for (int i=0; i < roles.size(); ++i) 
     delete roles[i]; 
} 

Stooge* Factory::make_stooge(int choice) { 
    switch(choice) { 
    case 1: 
     return larry.clone(); 
    case 2: 
     return curly.clone(); 
    case 3: 
     return moe.clone(); 
    default: 
     return nullptr; 
    } 
}