2013-02-10 58 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