2017-03-07 4 views
0

Compte tenu std::vector<A>::iterator et std::map<A, B>::iterator, comment puis-je appeler explicitement leurs destructeurs? Je ne connais pas les noms réels de ces types, car les types de membres ::iterator sont typedefs/aliases aux classes spécifiques à l'implémentation.Comment appeler explicitement le destructeur d'itérateurs std?

Je pose cette question, car je stocke ces itérateurs dans une union C++ non restreinte et Visual Studio me demande de gérer manuellement la destruction. I pourrait tout simplement ne pas appeler le destructeur de l'élément actif et supposer que les itérateurs n'ont pas besoin d'être nettoyés, mais que cela pue une mauvaise pratique.

+0

Cela sent comme si vous le faites mal. Mais je ne sais pas ce que tu fais, donc je ne peux pas t'aider à faire un autre, peut-être mieux. – rubenvb

Répondre

3

Comme ceci:

// let iter be vector<int>::iterator to be destroyed 
iter.std::vector<int>::iterator::~iterator(); 

Je ne connais pas les noms réels de ces types, parce que le :: iterator types de membres sont typedefs/alias aux classes spécifiques à l'implémentation.

Peu importe. Les alias de type sont également des noms de type.


LLVM semble avoir un bug avec ceci: https://bugs.llvm.org//show_bug.cgi?id=12350

Jusqu'à ce qu'il soit fixé, comme une solution de contournement, introduire un alias non imbriqué:

using iterator = std::vector<int>::iterator; 
iterator it; 
it.iterator::~iterator(); 

ou consultez le type que argument de modèle (ce code provient du rapport de bogue):

template <typename T> 
inline void placement_delete(T *x) 
{ 
    // C++ lacks placement delete, so fake it with a function 
    x->~T(); 
} 
+0

Ne fonctionnera pas si le type d'itérateur est un pointeur brut. –

+0

@RichardCritten ne semble pas être un problème selon la norme: 'La notation pour l'appel explicite d'un destructeur peut être utilisée pour n'importe quel nom de type scalaire' – user2079303

+0

GCC semble accepter cela, mais pas clang. https://godbolt.org/g/V098YM –

0

Le plus souvent, l'itérateur n'est qu'un pointeur vers la mémoire déjà allouée. À moins que les itérateurs ne soient créés à l'aide du nouveau

typedef std::vector<A>::iterator VecIter; 
VecIter* iter= new VecIter; 

il n'est pas nécessaire de supprimer. Si vous utilisez new, vous pouvez appeler delete pour la variable itérateur.

delete iter; 
+0

Je ne parle pas d'appeler delete sur un itérateur, mais d'appeler explicitement son destructeur. https://msdn.microsoft.com/en-us/library/6t4fe76c.aspx#Anchor_3 –

2
std::destroy_at(&iter); 

std::destroy et les amis sont une caractéristique C + 17. Si votre compilateur manque de soutien, il est trivial de vous mettre en œuvre:

template <typename T> 
void destroy_at(T* p) { 
    p->~T(); 
} 

Source.

+0

Très bien! Bon à savoir cela existe. Donc, avec impatience le support généralisé C++ 17! –