我有一个名为CConfig的类,我正在创建新对象:
std::vector< CConfig > docs;
CConfig newfile( "somefile.xml", "root" );
printf("%s", newfile.GetTagValue( "servername" )); // this works
docs.push_back( newfile );
当我使用.at方法
获取此对象时CConfig file = docs.at(0);
printf("%s", file.GetTagValue( "servername" )); // this crashes
问题出在哪里?
(对不起,如果格式化错误,但目前我不使用javascript,因为我的带宽已经结束,最大速度是1kb / s所以我稍后会尝试修复它)
CConfig.h:
class CConfig
{
TiXmlDocument m_doc;
TiXmlElement* m_pRoot;
bool m_bIsLoaded;
public:
CConfig ( void ) {};
CConfig ( const char * pszFileName, const char * pszRootName );
~CConfig ( void ) {};
const char* GetTagValue ( const char * pszTagName );
const char* GetTagAttribute ( const char * pszTagName, const char * pszAttributeName );
TiXmlElement* GetRootElement ( void ) { return m_pRoot; };
bool IsAvailable ( void ) { return m_bIsLoaded; };
};
CConfig.cpp
#include "CConfig.h"
CConfig::CConfig( const char * pszFileName, const char * pszRootName )
{
m_bIsLoaded = m_doc.LoadFile( pszFileName );
if( m_bIsLoaded )
m_pRoot = m_doc.FirstChildElement( pszRootName );
}
const char * CConfig::GetTagValue( const char * pszTagName )
{
if( m_bIsLoaded && m_pRoot )
{
TiXmlElement * element = m_pRoot->FirstChildElement( pszTagName );
if( element )
return element->GetText();
}
}
const char * CConfig::GetTagAttribute( const char * pszTagName, const char * pszAttributeName )
{
if( m_bIsLoaded && m_pRoot )
{
TiXmlElement * element = m_pRoot->FirstChildElement( pszTagName );
if( element )
return element->Attribute( pszAttributeName );
}
}
我正在使用tinyxml
答案 0 :(得分:3)
您的问题是指向旧内存的指针。将项添加到数组时,将复制该项。稍后您离开该范围并销毁原件,但问自己副本中的指针指向哪里?仍然是第一个(现在删除)对象的内存。糟糕,
最简单的修复(避免大型复制操作)是将m_doc
转换为共享指针(在C ++ 11中的标准中可用,或者在C ++ 03中通过Boost提供)。然后,那将为你处理一切明智的规则。并且由于底层内存不会移动,m_pRoot
将保持有效,直到最后一个副本被删除。
答案 1 :(得分:2)
如果副本空间不是问题,请通过正确添加复制构造函数来修复违反规则3:
CConfig(const CConfig& obj)
: m_doc(obj.m_doc)
, m_bLoaded(obj.m_bLoaded)
, m_pRoot()
{
if (m_bLoaded)
m_pRoot = m_doc.GetRootElement();
}
赋值运算符也可能是有序的,但是如果你不需要它,可以通过将它(但不是实现它)声明为private
来隐藏它,或者使用C ++ 11 delete
属性特征。
有趣的是,您甚至不需要m_bLoaded
成员。非NULL根指针可以指示您的加载状态,但这是一个单独的问题。这至少足以让你开始运行。