2017-05-03 1 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; 
} 

C'est l'exception que je reçois lorsque j'exécute le débogueur.Exception unordered_set de Visual Studio, fonctionne sur les blocs de code

<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

Où avez-vous lu que l'utilisation de 'malloc' pour créer des types de classes complexes en C++ serait acceptable? Nous devons corriger la ressource d'apprentissage que vous utilisiez. –

+0

Je ne savais pas que jouer juste autour, btw pourquoi cela a-t-il fonctionné sur gcc? – praveen

+0

Ce n'est pas le cas. Il est simplement apparu, par pur hasard. –

Répondre

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

En utilisant *Arr ou Arr[i] de quelque manière que c'est mal formé pas de diagnostic nécessaire, car aucun objet de type MyStruct existe à ne importe où Arr points. Créer simplement un bloc de mémoire suffisamment grand pour contenir un objet ne crée pas d'objet.

De nombreux compilateurs vous permettent de faire cela pour les anciens types de données et agissent comme si c'était un comportement défini (ce n'est pas le cas, mais ils le permettent).

Il ne fonctionne pas de manière fiable pour les types non-pod sur n'importe quel compilateur.

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

Un comportement non défini qui fonctionne n'est pas un code de preuve correct.

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

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

C'est la bonne façon de construire un objet qui est une copie de tk dans un endroit où aucun objet existe. Notez que vous êtes responsable de la destruction manuelle de cet objet.

Vous pouvez également:

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

et construire un objet dans chacune des "trous MyStruct de taille". Alors

Arr[0] = tk; 

serait légal.

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

return 0; 

Avant votre retour, vous devez détruire chaque objet que vous avez créé pour des raisons de santé mentale.

Arr[0].~MyStruct(); 

si vous ne construit une ou

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

si vous avez construit tous les 10.

En plus:

Il y a quelques arguments au sujet si la norme peut être un peu ambigu sur si vous pouvez prendre un tampon de taille de 10 MyStruct et le traiter comme un tableau; cependant, la plupart le considéreraient comme un défaut s'il n'était pas possible de le faire.

En règle générale, vous ne souhaitez pas utiliser les données malloc 'd pour contenir des types non-POD. Appelez simplement new MyStruct[10] à la place.

+0

Merci beaucoup! – praveen

+0

et btw, comment puis-je réaffecter sur des types non-POD? – praveen

+0

@praveen Ce n'est pas le cas.Il n'y a pas d'API pour étendre un bloc d'allocation sans copier en C/C++, et seuls les objets "trivialement copiables" peuvent être copiés en toute sécurité par la procédure realloc. – Yakk