Iterating Baselists and removing objects [SOLVED]



  • On 26/08/2016 at 04:22, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R17 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    This is probably a simple thing but I wanted to get some clarity since search the forum didn't provide any meaningful results. I have a situation in C++ where I'd like to loop a list of materials and delete them. I understand Baselists Remove() function will remove them from the document, and according to documentation I'm supposed to free them as the owner, but I'm wondering about my ability to do a GetNext for the next item in the list if the object has already been removed or freed. How does that work out?



  • On 26/08/2016 at 09:05, xxxxxxxx wrote:

    Hi eldiren,
     thanks for writing us.
    With reference to your request, I confirm there's no chance to effectively use the GetNext() method once the object has been removed. Infact although the pointed object is still valid, being removed from the document, can't provide a valid pointer to the next material thus returning nullptr if invoked after removal. Even worse if the GetNext() is invoked after the deletion of the object, it will result in calling a method of an object no longer existing in the memory.
    To effectively delete materials while looping over the them,  it's more comfortable to use a temporary pointer to store the pointer to the material object to be removed, then update the original pointer to point to the next object and proceed in removing and freeing the temporary pointer previously created.

      
     BaseMaterial* pCurrentBaseMat = doc->GetFirstMaterial();  
     while (pCurrentBaseMat)  
     {  
    if (pCurrentBaseMat->GetName() == "RemoveMe")  
    {  
     BaseMaterial* pTempBaseMat = pCurrentBaseMat;  
     pCurrentBaseMat = pCurrentBaseMat->GetNext();  
     pTempBaseMat->Remove();  
     BaseMaterial::Free(pTempBaseMat);  
    }  
    else  
     pCurrentBaseMat = pCurrentBaseMat->GetNext();  
     }  
    

    Alternatively  you could arrange a different design where a first loop runs over all the materials and store on a list the pointers of the materials to be deleted, and a second where, running over this list, the effective removal and resource deallocation of the marked items takes place.

      
     BaseMaterial* pCurrentBaseMat = doc->GetFirstMaterial();  
     AtomArray* pRemovableItems = AtomArray::Alloc();  
     while (pCurrentBaseMat)  
     {  
    if (pCurrentBaseMat->GetName() == "RemoveMe")  
     pRemovableItems->Append((C4DAtom* )pCurrentBaseMat);  
    pCurrentBaseMat = pCurrentBaseMat->GetNext();  
     }
     for (Int32 i = 0; i < pRemovableItems->GetCount(); i++)  
     {  
    BaseMaterial* pTmpBaseMat = (BaseMaterial* )pRemovableItems->GetIndex(i);  
    pTmpBaseMat->Remove();  
    BaseMaterial::Free(pTmpBaseMat);  
     }  
    

    Best, Riccardo



  • On 26/08/2016 at 15:23, xxxxxxxx wrote:

    Thanks. That worked out well.


Log in to reply