2017-05-03 5 views
0
typedef struct MyStruct { 
    unordered_set<int> mySet; 
}MyStruct; 

int main(){ 
    unordered_set<int> sset{ 1,2,3,4,5 }; 
    MyStruct tk; 
    tk.mySet = sset; //This works fine. 
    for (auto x : tk.mySet) printf("%d ", x); 

    MyStruct *Arr = (MyStruct *)malloc(10* sizeof(MyStruct)); 

    Arr[0] = tk; // This isnt working, giving an exception 
        //the same code runs as expected on codeblocks 

    for (auto x : Arr[0].mySet) printf("%d ", x); 

    return 0; 
} 

これは、私がデバッガを実行したときの例外です。 *Arr又はArr[i]を使用Visual Studio unordered_set例外は、Codeblockで動作します

<fileName>.exe!std::list<int,std::allocator<int> >::_Orphan_ptr(std::_List_node<int,void *> * _Ptr) Line 1919 C++ 
<fileName>.exe!std::list<int,std::allocator<int> >::clear() Line 1501 C++  
<fileName>.exe!std::_Hash<std::_Uset_traits<int,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int> >,std::allocator<int>,0> >::_Copy(const std::_Hash<std::_Uset_traits<int,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int> >,std::allocator<int>,0> > & _Right) Line 843 C++  
<fileName>.exe!std::_Hash<std::_Uset_traits<int,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int> >,std::allocator<int>,0> >::operator=(const std::_Hash<std::_Uset_traits<int,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int> >,std::allocator<int>,0> > & _Right) Line 291 C++  
<fileName>.exe!std::unordered_set<int,std::hash<int>,std::equal_to<int>,std::allocator<int> >::operator=(const std::unordered_set<int,std::hash<int>,std::equal_to<int>,std::allocator<int> > & _Right) Line 187 C++ 
<fileName>.exe!main() 
[External Code]  
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll] 
+1

ここで 'malloc'を使ってC++で複雑なクラス型を作るのは大丈夫でしょうか?使用している学習リソースを修正する必要があります。 –

+0

私はそれを周りに遊んでいることを知っていない、btwなぜgccで動作したのですか? – praveen

+0

それはしませんでした。純粋なチャンスで、それは単に出現した。 –

答えて

4
MyStruct *Arr = (MyStruct *)malloc(10* sizeof(MyStruct)); 

任意の方法でタイプMyStructのはオブジェクトがどこArr点に存在しないので、必要ない診断が悪い形成されていません。オブジェクトを保持するのに十分な大きさのメモリブロックを作成するだけでは、オブジェクトは作成されません。

多くのコンパイラでは、普通の古いデータ型に対してこれを実行させ、定義された動作であるかのように振る舞います(そうではありませんが、許可します)。

コンパイラの非ポッドタイプでは、確実に動作しません。

Arr[0] = tk; // This isnt working, giving an exception 
       //the same code runs as expected on codeblocks 

未定義の動作は動作していないという証拠は正しいコードです。オブジェクトが存在しない場所でtkのコピーであるオブジェクトを構築するための適切な方法である

MyStruct *Arr = (MyStruct *)malloc(10* sizeof(MyStruct)); 

::new((void*)&Arr[0]) MyStruct(tk); 

。そのオブジェクトを手動で破棄することに責任があることに注意してください。

あなたは可能性も:

for (int i = i; i < 10; ++i) 
    ::new((void*)(Arr+i)) MyStruct{}; 

と "MyStructサイズの穴" の各オブジェクトを構築。次に

Arr[0] = tk; 

は合法です。

for (auto x : Arr[0].mySet) printf("%d ", x); 

return 0; 

戻ってくる前に、作成した各オブジェクトを健全性の問題として破壊する必要があります。

Arr[0].~MyStruct(); 

あなたはさておき、すべての10

を構築している場合、あなたは一つだけ、または

for (int i = 0; i < 10; ++i) 
    Arr[i].~MyStruct(); 

を構築している場合:

標準は少しかもしれ場合についていくつかの議論があります。あなたが10 MyStructのサイズのバッファを取ってそれを配列のように扱えるかどうか不明です。しかし、それを行うことができない場合、ほとんどの人はそれを欠陥とみなします。

一般的に、mallocのデータを使用して非PODタイプを保持することは望ましくありません。代わりにnew MyStruct[10]に電話してください。

+0

ありがとう! – praveen

+0

とbtw、私はどのように非PODタイプにreallocするのですか? – praveen

+0

@praveenあなたはしません。C/C++でのコピーを行わずにアロケーションブロックを拡張するAPIはなく、reallocプロシージャによって "trivially copyable"オブジェクトだけを安全にコピーできます。 – Yakk

関連する問題