gpt4 book ai didi

c++ - 从 std::map 中删除对象时销毁对象

转载 作者:太空狗 更新时间:2023-10-29 23:45:32 25 4
gpt4 key购买 nike

当我从 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;
}

这是输出:

./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

问题是:

  1. 为什么默认构造函数被调用了这么多次,而我只是使用我自己的构造函数创建 3 个对象?
  2. 我可以吗,基于这个例子说,每次我从std::map,它的析构函数叫做 ?这是一个人的一般行为吗?std::map ?我找不到此信息。
  3. 如果我正在存储指向对象的指针(我正在使用“new”运算符创建它们)怎么办?什么时候调用delete

最佳答案

std::map 存储您插入的对象的拷贝。当。。。的时候对象被删除,正是这个拷贝被破坏。所以在 m[1] = t1; 之后,有两个相同的实例CTestMap:t1 和 map 中的那个。

此外:m[1] = t1; 将首先在 map 中创建一个新条目,使用默认构造函数,然后将 t1 分配给它。

一般来说,如果你想像这样跟踪实例生命周期,您需要提供用户定义的复制构造函数和赋值运算符 which trace 也是如此。你可能想输出所有跟踪中的 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;
}
};

你可能想添加额外的信息(比如 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;
}
}

(最后:我认为微软已经抢占了 C 前缀类,所以你应该避免它。如果你想要一个前缀,选择其他的,以避免混淆。)

关于c++ - 从 std::map 中删除对象时销毁对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18098388/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com