2016-08-25 4 views
0

匿名のユニオンを使用することに決めたため、あるタイプのマップを含むクラスを作成しようとしています。クラス内部のマップにアクセスすると、セグメンテーションフォールトが発生する

#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

マップを作成し、そのデストラクターを手動で呼び出すには、プレースメントnewを使用する必要があります。 「C++ unrestricted union」の検索を行うと、多くの優れたリソースが見つかります。 – Cornstalks

+0

テンプレートを使ってクラスを宣言したくないのですか? – MikeCAT

+0

@MikeCATいいえ、これは私がやろうとしている他のものの単純化されたバージョンです.2つのマップでユニオンが必要です – Orfby

答えて

3

私はタイプの代わりに、労働組合をテンプレート化を示唆している、しかし:しかし、私のコードは、私はマップを(このケースでは、私は、コンストラクタとデストラクタの両方でセグメンテーション違反を得る)にアクセスしようとすると、セグメンテーションフォールトを与えますこれはおそらくあなたを助けます。

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

第二の例は、非PODの組合員に対処する方法を示します。

それは私が今もののMSCVにそれをテストカントこの

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>(); } 
    } 

のようになります。

あなたはそれが「非自明」メンバ関数を持っているのでstd::mapタイプを含む

2

ほとんどのSTLコンテナは組合にすることはできません明示的に非PODの組合型を構築し、破壊する必要があります。ユニオンの内部にできることとできないことについての詳細は、wikiを参照してください。

ユニオンは、複数のデータ型間でメモリを共有するために使用されます。 std::mapコンテナはヒープは各ノードの実際のデータを格納するのに必要なメモリを割り当てます。これらのヒープ割り当ては、共用体にはありません。

関連する問題