Destructor被调用两次,而没有复制构造函数或赋值运算符被调用
Destructor Called Twice While No Copy Constructor or Assignment Operator Gets Callled
我有一个类:
class A
{
public:
A()
{
std::cout << "Constructor called" << std::endl;
}
~A()
{
std::cout << "Destructor called" << std::endl;
}
A(const A& another)
{
std::cout << "Copy constructor called" << std::endl;
}
A& operator=(const A& another)
{
std::cout << "Assignment operator= called" << std::endl;
}
};
在我非常复杂的项目中,我在启动应用程序后得到了以下输出:
Constructor called
但当我Ctrl+C终止我的应用程序时:
Destructor called
Destructor called
在整个过程中,没有调用复制构造函数或赋值运算符。
我的类A
有动态内存分配,我必须在析构函数中释放它,但析构函数不知怎么被调用了两次,这非常糟糕。
我不知道是什么原因导致了这个问题。
我在谷歌上搜索了很多。很多关于"析构函数调用两次"的问题都是因为隐式调用了复制构造函数(赋值运算符)。
谢谢。
Peter
如果您以某种方式调用析构函数两次,那么可能有两个对象认为它们通过指针拥有析构函数。
如果你确实有两个对象认为它们拥有这个对象,可以考虑使用一个引用计数的指针,如Boost::shared_ptr或tr1::shared_pt来包含它。这样你就不必担心最后是谁调用析构函数了。
除了调试器之外,您还可以尝试Valgrind(memcheck)来查找程序删除已释放对象的位置。在这种情况下,它可能不会提供比调试器更多的细节,但您迟早应该学会使用Valgrind(memcheck)。
另一个偏执的策略是确保在删除任何内部指针后将其设置为NULL。
很可能您有另一个没有显示的构造函数,或者您多次显式或通过delete
调用析构函数。
调试器或额外的cout
将比我们在这种情况下更有用。
在析构函数中粘贴断点。然后,无论何时调用它,都可以获取堆栈跟踪,并查看它是从哪里调用的。
编辑:
可以期望复制省略会对像这样的琐碎调试语句造成严重破坏。
在我的例子中,我没有使用指针,但析构函数仍然被调用了两次。我所做的解决问题的方法是覆盖复制分配运算符MyClass& operator=(const MyClass& other)
。不太清楚为什么自动生成的运算符会导致问题,但看起来确实会。
- 当从函数参数中的临时值调用复制构造函数时
- 为什么调用复制构造函数而不是移动构造函数?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 编译器调用复制运算符而不是移动运算符
- push_back std::vector,则重复调用复制构造函数
- 为什么调用复制构造函数来构造空unique_ptr向量?
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 我打算调用initializer_list构造函数,如果存在,则事先调用复制构造函数:为什么?
- C++ - 从移动分配运算符调用复制分配
- 构造函数初始值设定项列表未调用复制构造函数
- 为什么在我的代码中调用复制构造函数而不是移动构造函数?
- std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数
- 通过引用传递对象时是否调用复制构造函数?
- 如果函数按值传递并按值返回,将调用复制构造函数多少次
- 为什么要抛出引用调用复制构造函数的异常?
- 为什么即使参数标记为"const",也会调用复制构造函数?
- Clang-Tidy:移动构造函数通过调用复制构造函数来初始化类成员
- 为什么当我添加一个不同的对象(复制构造函数中的参数)时调用复制构造函数?
- 为什么调用复制构造函数,当我只返回对象 c++ 的引用时
- 为什么在下面的代码中调用复制构造函数两次