Jos*_*siP 2 c++ stdmap std erase
当我从中删除元素时,如果调用了默认析构函数,我感到很好奇std::map。这是我做的一个例子:
class CTestMap{
public:
CTestMap() {
std::cout << "default constructor called" << std::endl;
}
CTestMap(int id) {
std::cout << "created object: " << id << std::endl;
m_id = id;
}
~CTestMap() {
std::cout << "destroyed object: " << this->m_id << std::endl;
}
int get_id(){
return m_id;
}
int m_id;
};
int main(void){
std::map<int, CTestMap>m;
std::map<int, CTestMap>::iterator m_it;
std::cout << "created map " << std::endl;
CTestMap t1(1);
std::cout << "created test object: " << t1.get_id() << std::endl;
CTestMap t2(2);
std::cout << "created test object: " << t2.get_id() << std::endl;
CTestMap t3(3);
std::cout << "created test object: " << t3.get_id() << std::endl;
m[1] = t1;
m_it = m.find(1);
std::cout << "inserted test object: " << m_it->second.get_id() << std::endl;
m[2] = t2;
m_it = m.find(2);
std::cout << "inserted test object: " << m_it->second.get_id() << std::endl;
m[3] = t3;
m_it = m.find(3);
std::cout << "inserted test object: " << m_it->second.get_id() << std::endl;
m_it = m.find(1);
std::cout << "will now erased test object: " << m_it->second.get_id() << std::endl;
m.erase(m.find(1));
std::cout << "erased test object: " << m[1].get_id() << std::endl;
m_it = m.find(1);
std::cout << "object shall no longer exist: " << m_it->second.get_id() << std::endl;
while(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这里是输出:
./htest
created map
created object: 1
created test object: 1
created object: 2
created test object: 2
created object: 3
created test object: 3
default constructor called
destroyed object: 9377935
destroyed object: 9377935
inserted test object: 1
default constructor called
destroyed object: 9377935
destroyed object: 9377935
inserted test object: 2
default constructor called
destroyed object: 9377935
destroyed object: 9377935
inserted test object: 3
will now erased test object: 1
destroyed object: 1
default constructor called
destroyed object: 158830600
destroyed object: 158830600
erased test object: 158830600
object shall no longer exist: 158830600
Run Code Online (Sandbox Code Playgroud)
问题是:
std::map,其析构函数都称为?这是一般行为
std::map吗?我找不到此信息。delete什么时候才叫?std::map存储您插入的对象的副本。删除对象后,此副本将被破坏。因此,之后m[1] = t1;有两个相同的实例
CTestMap:t1和映射中的一个。
同样:m[1] = t1;将首先使用默认构造函数在地图中创建一个新条目,然后分配t1给它。
通常,如果要这样跟踪实例生存期,则需要提供用户定义的副本构造函数和赋值运算符,它们也要进行跟踪。您可能希望this在所有跟踪中输出指针。(另一种技术是用不可变的唯一标识符来修饰每个对象:
#define TRACE(m) std::cout << #m << '(' << m_objectId << ')' << std::endl
static int currentObjectId = 0;
class TestMap
{
int m_id;
int const m_objectId;
public:
TestMap()
: m_id( 0 )
, m_objectId( ++ currentObjectId )
{
TRACE(DFLT);
}
TestMap( int id )
: m_id( id )
, m_objectId( ++ currentObjectId )
{
TRACE(CTOR);
}
TestMap( TestMap const& other )
: m_id( other.m_id )
, m_objectId( ++ currentObjectId )
{
TRACE(COPY);
}
~TestMap()
{
TRACE(DTOR);
}
TestMap& operator=( TestMap const& other )
{
m_id = other.m_id;
TRACE(ASGN);
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
您可能还希望向m_id跟踪添加其他信息(例如)。
另外:您的最后一个输出调用未定义的行为。之后
m.find(i),您应该首先检查迭代器是否未返回m.end()。如果有,则不允许取消引用。因此,您的测试输出应类似于:
void
testOutput( std::map<int, TestMap> const& m, int i )
{
std::map<int, TestMap>::const_iterator entry = m.find( i );
if ( entry == m.end() ) {
std::cout << "no object at " << i << std::endl;
} else {
std::out << "object " << entry->second.m_id << " at " << i << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
(最后:我认为Microsoft已抢占了C类的前缀,因此您应该避免使用它。如果需要前缀,请选择其他选项以避免混淆。)
| 归档时间: |
|
| 查看次数: |
4640 次 |
| 最近记录: |