多次调用同一对象的析构函数,其结果与标准中描述的不一样
Invoking the destructor of the same object multiple times, result is not the same as described in standard
我使用的是MS Visual Studio 2010。
我实现了一个双链表。
我想知道为什么在main函数中调用Clean方法后,调用对象的析构函数,在我引用对象后没有引发错误。
这里是我的一些双链表方法(相对于我的问题):
/*DoubleLinkedList.cpp */
DoubleLinkedList::~DoubleLinkedList(void)
{
cout << "Destructor invoked" << endl;
// as for data nodes memory is allocated in heap we have to release it:
const Node* const_iterator = m_head.m_next;
while (const_iterator != &m_tail)
{
const_iterator = const_iterator->m_next;
delete const_iterator->m_prev;
}
}
void DoubleLinkedList::Clean(void)
{
cout << "Clean invoked" << endl;
this->~DoubleLinkedList(); /* According to C++ 11 standart: Once a destructor is invoked for an object, the object no longer exists*/
}
/* main.cpp */
int main(int argc, char* argv[])
{
DoubleLinkedList list;
Circle c1, c2(MyPoint(1,1),50), c3(MyPoint(2,2),30);
list.Front(&c1);
list.Front(&c2);
list.Front(&c3);
list.Show();
list.Sort();
list.Show();
list.Clean();
list.Show(); /* Recall how Clean method is implemented. As list no longer exist, run-time error is expected here, but flow of executon continues and Show, Push_back preforms fine*/
list.Push_back(&c1);
list.Push_back(&c2);
list.Push_back(&c3);
问题: *如c++ 11标准中所述,在调用析构函数后-对象不再存在*,为什么在调用析构函数后我仍然能够使用对象?
这里需要考虑的重要事项是对象的生存期。对象的生存期必须在为该对象分配存储的时间内存在。在分配存储的时间内,多个对象可以一个接一个地存在于一个存储位置。
通常,当对象被销毁时(通过超出作用域或调用delete
),对象的生命周期结束,然后它的内存被释放。然而,当显式调用析构函数时,所做的只是结束对象的生命周期。该标准没有对象"不存在"的定义,但它有其生命周期结束的概念。
类型为
T
的对象的生存期结束于:
- 如果
T
是具有非平凡析构函数(12.4)的类类型,则开始析构函数调用,或- 对象占用的存储空间被重用或释放。
现在,在对象生命周期结束并且在其存储被释放之前的状态下,只有非常特定的事情可以做。标准定义了指针和左值在这种状态下可以做的事情。在您的示例中,list
是一个全局值,因此我们将查看其规则:
[…在对象生命周期结束后和对象存储之前被占用的被重用或释放,任何指向原始对象的glvalue都可以被使用,但只能以有限的方式使用。[…如果:
程序有未定义的行为
- 左值到右值的转换(4.1)应用于这样的glvalue,
- glvalue用于访问非静态数据成员或调用对象的非静态成员函数,或者
- glvalue被隐式转换(4.10)为对基类类型的引用,或者
- glvalue用作
static_cast
(5.2.9)的操作数,除非最终转换为cvchar&
或cvunsigned char&
,或- glvalue用作
dynamic_cast
(5.2.7)的操作数或typeid
的操作数。
第二个列表项在这里适用。你有未定义的行为,因为你在对象生命周期结束后访问非静态成员函数。
在对象被销毁(即调用析构函数)后使用它是UB。UB表示未定义行为。所以…
相关文章:
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- 使用CMake检测支持的C++标准
- 用C++20 fmt限制结果的总大小
- 如何理解C++标准N3337中的expr.const.cast子句8
- 如何返回一个类的两个对象相加的结果
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- C++标准:是否有结果对象?
- C++ 增强正则表达式与标准库正则表达式匹配结果
- 根据标准对结构向量进行排序,然后显示结果
- 将一个进程标准输出重定向到管道将产生不同的运行结果
- C++ 集合有序迭代 - 是迭代集合的结果,按标准排序
- 执行控制台程序,写入标准输入并使用管道读取结果
- 读取文件和使用getline进行标准输入的结果不同
- 如何在Linux上的c++中将数据管道到bzip2中并从其标准输出中获得结果数据?
- 类模板中名称解析的实际结果与c++ 03标准不同
- 通过输出参数返回结果,c++编码标准
- 标准中是否有任何引用支持以下结果?
- 多次调用同一对象的析构函数,其结果与标准中描述的不一样