2013-02-10 57 views
1

也許有人可以幫助我理解錯誤。std :: vector - error:無法刪除不是指針的對象

我寫這篇文章的代碼:

class Text 
{ 
private: 
    struct paragraph 
    { 
     vector<string> lines;  
    }; 

    vector<shared_ptr<paragraph>> paragraphs; 
public: 

    Text() 
    { 
     paragraphs.push_back(shared_ptr<paragraph>(new paragraph())); 
    } 
}; 

int main() 
{ 
    shared_ptr<Text> pText(nullptr); 
    Text text(); 
    pText.reset(&text); 
    return 0; 
} 

當我嘗試運行它
我得到這個錯誤:

1>c:\program files\microsoft visual studio 10.0\vc\include\memory(1664): error C2541: 'delete' : cannot delete objects that are not pointers 
1>   c:\program files\microsoft visual studio 10.0\vc\include\memory(1431) : see reference to function template instantiation 'void std::tr1::shared_ptr<_Ty>::_Resetp<_Ux>(_Ux (__cdecl *))' being compiled 
1>   with 
1>   [ 
1>    _Ty=Text, 
1>    _Ux=Text (void) 
1>   ] 
1>   c:\program files\microsoft visual studio 10.0\vc\include\memory(1607) : see reference to function template instantiation 'std::tr1::shared_ptr<_Ty>::shared_ptr<_Ux>(_Ux (__cdecl *))' being compiled 
1>   with 
1>   [ 
1>    _Ty=Text, 
1>    _Ux=Text (void) 
1>   ] 
1>   c:\documents and settings\owner\שולחן העבודה\e\class.cpp(29) : see reference to function template instantiation 'void std::tr1::shared_ptr<_Ty>::reset<Text(void)>(_Ux (__cdecl *))' being compiled 
1>   with 
1>   [ 
1>    _Ty=Text, 
1>    _Ux=Text (void) 
1>   ] 

是什麼意思「不能刪除不是指針對象」?
我不想刪除任何對象。

+0

不要像這樣使用shared_ptr。 – 2013-02-10 15:30:17

回答

2

該行Text text();不會做你認爲它做的事。

它解析它作爲一個功能名爲text它接受任何參數和返回Text類型的值的聲明。

這就是爲什麼你的行pText.reset(&text);不能編譯的原因。

但是,你真的希望該行編譯:你是關聯一個shared_ptr對象具有自動存儲時間值:當shared_ptr將走出去的範圍,它會嘗試delete該對象,從而導致在未定義的行爲(很可能是在這種情況下崩潰)。

+0

這只是一個輕度令人煩惱的解析,而不是最令人頭疼的解析。 – 2013-02-10 15:38:59

+0

@ K-ballo:呃,我認爲術語MVP用來表示那些被認爲是對象聲明的東西被解析爲函數聲明的情況。我將重述它。謝謝。 – 2013-02-10 15:46:53

+0

'文本文本();'是最令人敬畏的解析的文本書的例子。 – Puppy 2013-02-10 15:47:46

3

除了最棘手的解析,您的代碼包含一個根本缺陷:

你不能一個指向堆棧分配對象分配給shared_ptr

此代碼將導致其在實踐中意味着許多痛苦的未定義行爲:

shared_ptr<Text> pText(nullptr); 
Text text; 
pText.reset(&text); 

shared_ptr將嘗試delete &text在其生命週期結束。

+0

是的,這是一個繁榮。 – 2013-02-10 15:30:39

+0

@LuchianGrigore [我們只是說「繁榮」](http://www.imdb.com/title/tt0361748/quotes?qt=qt0558771).-) – 2013-02-10 15:33:35

+0

也沒有涉及共享所有權,所以應該有在這個代碼中根本沒有shared_ptr。 – 2013-02-10 15:34:16

0

main函數應該讀取。

int main() 
{ 
    shared_ptr<Text> pText(new Text); 
    return 0; 
} 

您有2個問題。首先,Text text()被解析爲函數聲明。其次,您將堆棧變量的地址傳遞給shared_ptr,其中delete是參考計數達到0時的對象。

您還應該考慮是否需要使用shared_ptr。你會不會與其他任何人分享這個指針,還是你只是想確保它正確地被破壞?在後一種情況下你可以考慮unique_ptr。你甚至都需要一個指針,你可以只分配堆棧上的對象嗎?

+1

其實沒有。這是沒有意義的,甚至不包括你的評論在我的答案下面。 'main'函數*應該被讀爲:'文本文本;'。而已。沒有指針 - 管理或非託管 - 必要的。 – 2013-02-10 15:44:37

+0

你也用'make_shared'構造'shared_ptr',不是那樣的。 – 2013-02-10 15:47:07

+0

@CatPlusPlus同意,你可以調用'make_shared'。然而,我寫的東西沒有錯。實際上,Meyers在Effective C++(3rd Edition)的第77頁上使用它。 – 2013-02-10 16:57:28