2016-08-25 1 views
0

Je tente de créer une classe qui contient une carte d'un type ou d'un autre, j'ai donc décidé d'utiliser une union anonyme. Mais mon code donne une erreur de segmentation lorsque je tente d'accéder à la carte (dans ce cas, je reçois une erreur de segmentation que dans le constructeur et le destructeur):L'accès à la carte à l'intérieur de la classe à l'intérieur de la classe donne un défaut de segmentation

#include <map> 
#include <string> 
#include <iostream> 

class Foo 
{ 
    private: 
     union 
     { 
      std::map<std::string, int> ints; 
      std::map<std::string, std::string> strings; 
     }; 

     bool fooContainsInts; 

    public: 

     Foo(bool containsInts) : fooContainsInts(containsInts) 
     { 
      if (containsInts) {ints = std::map<std::string, int>();} 
      else {strings = std::map<std::string, std::string>();} 
     } 

     ~Foo() 
     { 
      if (fooContainsInts) {ints.clear();} 
      else {strings.clear();} 
     } 
}; 

int main() 
{ 
    std::cout << "No segfault here!" << std::endl; 
    Foo foo(true); 
    std::cout << "This line doesn't get printed" << std::endl; 
    return 0; 
} 
+0

Vous devez utiliser placement new pour construire la carte et appeler manuellement son destructeur. Si vous faites des recherches pour "C++ Unrestricted Union", vous trouverez beaucoup de bonnes ressources. – Cornstalks

+0

Vous ne voulez pas déclarer une classe avec des modèles, n'est-ce pas? – MikeCAT

+0

@MikeCAT Non, ce n'est qu'une version simplifiée de quelque chose d'autre que j'essaie de faire, qui a besoin d'une union avec deux cartes – Orfby

Répondre

3

je suggère Templating le type au lieu d'une union, mais peut-être que cela vous aide.

http://en.cppreference.com/w/cpp/language/union

Le deuxième exemple vous montre comment traiter avec les membres du syndicat non-POD.

Il devrait ressembler à ceci

Foo(bool containsInts) : fooContainsInts(containsInts) 
    { 
     if (containsInts) { new (&ints) std::map<std::string, int>;} 
     else { new (&strings) std::map<std::string, std::string>;} 
    } 

    ~Foo() 
    { 
     if (fooContainsInts) { ints.~map<std::string, int>(); } 
     else { strings.~map<std::string, std::string>(); } 
    } 

Je ne peux pas le tester sur MSCV bien en ce moment.

Vous devez construire explicitement et destructives types d'union non-POD

2

La plupart des conteneurs STL, y compris le type std::map ne peut pas être dans une union car il a « membres non triviales » fonctions. Voir wiki pour plus d'informations sur ce qui peut et ne peut pas être dans une union.

Une union est utilisée pour partager la mémoire entre plusieurs types de données. Notez que le conteneur std::map va tas allouer la mémoire nécessaire pour stocker les données réelles pour chaque nœud. Ces allocations de tas ne seraient pas dans l'union.