c++ - 复制堆栈变量时异常的析构函数行为

标签 c++ visual-c++ destructor rule-of-three

我编写了一个测试来检查是否在对堆栈变量进行覆盖赋值之前调用了析构函数,但我找不到对结果的任何合理解释...

这是我的测试(在 Visual C++ 2008 Release模式下):

#include <iostream>
class C {
public:
 char* ptr;
 C(char p) { ptr = new char[100]; ptr[0] = p;}
 ~C() { std::cout << ptr[0] << ' '; delete [] ptr; }
};

int _tmain(int argc, _TCHAR* argv[])
{
 {
  C s('a');
  s = C('b');
  s = C('c');
  s = C('d');
 }
 std::cin.get();
 return 0;
}

如果我的假设为真,我希望得到“a b c d”,如果为假,我希望得到“d”。 相反,我得到“b c d x”。 “x”根据分配给 ptr 的内存量而变化,表示它正在读取随机堆值。

我相信正在发生的事情(如果我错了请纠正我)是每个构造函数调用都会创建一个新的堆栈值(我们称它们为 s1、s2、s3、s4),然后赋值让 s1.ptr 被覆盖s4.ptr。 s4 在复制后立即被销毁,但 s1(带有悬空 ptr)在离开作用域时被销毁,导致 s4.ptr 被双重删除,而原始 s1.ptr 没有被删除。

有什么方法可以解决这种不涉及使用 shared_ptrs 的无益行为吗?

编辑:将“删除”替换为“删除 []”

最佳答案

Rule of Three

您的应用程序行为未定义,因为如前所述,多个对象将共享对公共(public)指针的访问并尝试读取它...

三个规则规定每次定义其中之一:

  • 拷贝构造函数
  • 赋值运算符
  • 析构函数

那么您应该定义另一个,因为您的对象具有默认生成的方法不知道的特定行为。

编辑特殊异常(exception):
有时你定义析构函数只是因为你想要它是虚拟的,或者因为它记录了一些东西,而不是因为你的属性有一些特殊处理;)

关于c++ - 复制堆栈变量时异常的析构函数行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1531294/

相关文章:

c++ - 如何使用没有名称的 C++ 类?

C++ 使用 . 和 . 之间有什么区别?或 -> 对于链表

visual-c++ - 无法在 Visual Studio 2012 中链接 FFMpeg 库

c++ - 析构函数参数

c++ - 一些涉及类析构函数和删除运算符的内存管理问题?

c++ - boost::any 析构函数崩溃

c++ - 在类中实现移动语义的规范方法

c++ - wxDev C++ 中的 arc4random

c++ - 如何解决 LNK2001/2005 问题?

c++ - 使用 "expected a string literal, but found a user-defined string literal instead"C"'时是什么导致错误 'extern "?