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

这是我运行调试器时得到的异常。Visual Studio unordered_set异常,在代码块上工作

<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

我不知道,只是玩它,顺便说一句,为什么这对gcc工作? – praveen

+0

它没有。它纯粹出现在纯粹的机会中。 –

回答

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

以任何方式使用*ArrArr[i]是非法的构造没有诊断必需的,因为没有MyStruct类型的对象存在于任何地方Arr点。简单地创建一个足够容纳一个对象的内存块不会创建一个对象。

许多编译器会让你对普通的旧数据类型做这件事,并且就像它是定义的行为一样(它不是,但它们允许它)。

它在任何编译器上都不能可靠地工作于非pod类型。

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

未定义的行为工作不是证据代码是正确的。

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

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

即构造一个对象,它是的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(); 

如果只建造了一个,或

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

如果你构建的所有10

旁白:

大约有如果标准可能有点一些参数含糊不清如果你可以采取一个大小为10 MyStruct的缓冲区并将其视为一个数组;然而,如果无法做到这一点,大多数人会认为这是一个缺陷。

作为一般规则,您不希望使用malloc'd数据来保存非POD类型。请拨打new MyStruct[10]

+0

非常感谢! – praveen

+0

和顺便说一句,我如何realloc非POD类型? – praveen

+0

@praveen你没有。没有API可以扩展一个分配块而不用在C/C++中复制,并且只能通过realloc程序安全地复制“可复制的”对象。 – Yakk