2017-05-03 131 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