2017-05-04 1 views
0

내 코드를 살펴 유무 :포인터 벡터를 복제하면 어떻게 든 반복자를 복제 할 수 있습니까?

#include<vector> 
#include<algorithm> 
#include<iostream> 
using namespace std; 

class AbstractBase 
{ 
protected: 
    int ident; 
public: 
    virtual void add() = 0; 
    int getIdent()const {return ident;} 
    virtual ~AbstractBase(){}; 
    virtual AbstractBase* clone()const =0; 
}; 

class Derived1 :public AbstractBase 
{  
public: 
    Derived1(int i) 
    { 
     ident=i; 
    }; 
    virtual void add() override 
    { 
     ident+=1; 
    } 
    virtual AbstractBase* clone() const override 
    { 
     return new Derived1 (*this); 
    } 
}; 

class Derived2 :public AbstractBase 
{  
public: 
    Derived2(int i) 
    { 
     ident=i; 
    } 
    virtual void add() override 
    { 
     ident+=2; 
    } 
    virtual AbstractBase* clone() const override 
    { 
     return new Derived2(*this); 
    } 
}; 

class cloneFunctor 
{ 
public: 
    AbstractBase* operator() (AbstractBase* a) const 
    { 
     return a->clone(); 
    } 
}; 

struct IdentCompare 
{ 
    bool operator()(AbstractBase* f) 
    { 
     return f->getIdent() >5; 
    } 
}; 

void WorkWithClonedVector(vector<AbstractBase*>origList,vector<AbstractBase*>::iterator it) 
{ 
    vector<AbstractBase*> tempList; 
    transform(origList.begin(),origList.end(),back_inserter(tempList),cloneFunctor()); 
    //NEED TO FIND ITERATOR AGAIN-->ANY OTHER OPTION? 
    vector<AbstractBase*>::iterator tempIt=find_if(tempList.begin(),tempList.end(),IdentCompare()); 
    (*tempIt)->add(); 
    cout<<"local list:\n"; 
    for(unsigned int i=0;i<tempList.size();++i) 
    { 
     cout<<"Element "<<(i+1)<<": "<<tempList[i]->getIdent()<<'\n'; 
     delete tempList[i]; 
    } 
    cout<<"Original Iterator still pointing to: "<<(*it)->getIdent()<<'\n'; 
    tempList.clear(); 
} 


int main() 
{ 
    Derived1 d1(1); 
    Derived1 d1b(2); 
    Derived2 d2(7); 
    Derived2 d2b(5); 
    vector<AbstractBase*> List; 
    List.push_back(&d1); 
    List.push_back(&d1b); 
    List.push_back(&d2); 
    List.push_back(&d2b); 
    vector<AbstractBase*>::iterator iter = find_if(List.begin(),List.end(),IdentCompare()); 
    WorkWithClonedVector(List,iter); 
    cout<<"Original List not changed:\n"; 
    for(unsigned int i=0;i<List.size();++i) 
    { 
     cout<<"Element "<<(i+1)<<": "<<List[i]->getIdent()<<'\n'; 
    } 
} 

당신은 내가 성공적으로 안전하게 원본 목록에서 아무 것도 변경하지 않고 임시 목록 작업을하기 위해 WorkWithClonedVector 내에서 vector<AbstractBase*>를 복제하는 데 성공 볼 수 있듯이. WorkWithClonedVector의 매개 변수 목록에서 이터레이터를 "복제"할 수있는 가능성이 있는지 궁금 해서요. find_if을 두 번 사용할 필요가 없습니까? 매개 변수 목록의 반복기가 원래 목록의 세 번째 요소를 가리키는 경우 복제 된 반복기가 복제 된 목록의 세 번째 요소를 가리 키기를 바랍니다. 당신은 당신이에 의해 origList을 통과해야 std::vector

auto tempIt = tempList.begin() + (it - origList.begin()); 

Demo

주 (CONST)와 함께 작업 할 때,

auto tempIt = std::next(tempList.begin(), std::distance(origList.begin(), it)); 

또는 : 코드에서

+1

[OT] : 'WorkWithClonedVector'에 메모리 누수가 있습니다. 'Clone' 메쏘드가'std :: unique_ptr '를 반환하는 것보다 낳습니다. (당신은 공변 변종을 사용하지 않으므로, 여분의 메쏘드를 추가 할 필요가 없습니다). – Jarod42

+1

[OT] : const 참조로'std :: vector'를 전달하십시오. 그리고 당신은'getIdent()','clone()','operator()'메소드에'const'를 추가 할 수 있습니다. – Jarod42

+0

thx, 나는 당신의 제안 중 일부를 – airborne

답변

3

대신 사용할 수 있습니다 반복자가 동일한 범위에 속하지 않으므로 std::distance(origList.begin(), it));은 UB가됩니다.

+0

thx로 편집했지만, "cygwin_exception :: open_stackdumpfile : 스택 추적을 * .exe.stackdump"런타임 오류로 보내고 있습니다. 함수를 매개 변수로 포인터를 사용하여 작업 할 수 있습니다 : – airborne

+0

void WorkWithClonedVector (Vector * origList, vector :: iterator * it) { \t vector tempList; transform (origList-> begin(), origList-> end(), back_inserter (tempList), cloneFunctor()); 벡터 :: iterator tempIt = tempList.begin() + 거리 (origList-> begin(), * it); (* tempIt) -> add(); \t cout << "로컬 목록 : \ n"; \t for (부호없는 int i = 0; i getIdent() << '\ n'; \t tempList.clear(); }' – airborne

+1

@airborne : 내 의견의 수정 중 일부는 문제를 해결하는 데 필요합니다. 링크는 작동 버전과 함께 제공됩니다. – Jarod42

관련 문제