析构函数在 C++ 中测试深层/浅层复制时无法解释的行为

destructor's unexplained behavior while testing deep/shallow copy in C++

提问人:Waqar Ahmed 提问时间:4/10/2022 更新时间:4/11/2022 访问量:67

问:

class String
{
  private:
    char* ptr;
  public:
  
    String(const String& s1)
    {
       int len = strlen(s1.ptr);
       ptr = new char[len+1];
       strcpy(ptr,s1.ptr);
       
    }
    String(char* c)
    {
      int len = strlen(c);
       ptr = new char[len+1];
       strcpy(ptr,c);
       
    }
    ~String()
    { 
      cout<<"DELETING\n";
      delete[] ptr;
    }
    void display()
    {cout<<ptr;}
};

int main()
{
String s("Waqar"); String* s2  =&s;
String s1(s);
delete s2;
s1.display();

直到倒数第二行都很好。调试时,它会抛出一个错误,影响未知信号,并且永远不会执行。 作为一个菜鸟,我在 c++ 中测试了深层和浅层复制的概念,因此写了这个垃圾。 我哪里做错了?delete s2s1.display()

C++ OOP 析构函数 复制构造函数

评论

3赞 HolyBlackCat 4/10/2022
你只能你.deletenew
0赞 Waqar Ahmed 4/10/2022
PTR是一个“新”的。或者指向动态创建的内存,可以这么说。
1赞 Nathan Pierson 4/10/2022
@WaqarAhmed 但事实并非如此。s2
0赞 Waqar Ahmed 4/10/2022
那么,如果不是从 new 创建的,为什么它会调用析构函数呢?
0赞 aschepler 4/10/2022
的唯一用途是 type ,所以你不能和 type 一起使用 。您的程序具有未定义的行为,并且可能发生任何事情。newchar[]deleteString

答:

0赞 Dunes 4/10/2022 #1

s2指向 。它是一个指针,根本不是副本(浅层或其他)。它从未被 分配过任何内存。因此,当您尝试删除时,您要求程序释放堆栈上不受 new/delete 管理的内存。在这种情况下不要。这是一个错误。你的析构函数在这里没有错。snews2delete s2

下面是一个示例程序,详细介绍了析构函数的执行方式和时间 调用了不同的点,并且只分配了 的内存。deletenew

// declare `copy`, but do not initialise it just yet. We want to
// initialise it from `s` (which is not yet declared)
String* copy;
{
    // declare and initialise `s`, and copy "Wagner" into s.ptr
    String s("Wagner");
    // create a new String on the heap, initialised from `s`
    // this is a deep copy because of how you wrote String(String&)
    copy = new String(s);
    s.display();
    // `s` falls out of scope at the end of this block
    // this means that s.~String() is invoked
}
// `copy` is unaffected as it was declared in the outer scope, 
// and because it is a deep copy. Had it been a shallow copy
// then it would be broken as its `char* ptr` would not be valid
// any more.
copy->display();
// copy->~String() is invoked when copy is deleted
delete copy;

评论

0赞 Waqar Ahmed 4/11/2022
感谢您的解释。但是括在括号之间的 c++ 的这个功能是什么。我以前没见过这个。这是整个部分。 也是第一行 它看起来不像一个函数或一个类语法String* copy;
0赞 PaulMcKenzie 4/11/2022
@WaqarAhmed 大括号用于定义本地执行范围。它从一开始就存在于C++中,并不是一个新功能。它甚至存在于 C 语言中。
0赞 Dunes 4/11/2022
String* copy;是一个声明。这意味着我可以将声明与初始化分开。我这样做是为了让它的范围比 .但是我不能立即初始化,因为它是从 . 是一个“复合语句”或“块”,它只是将一组语句(如循环和函数)捆绑在一起。在块中声明的任何对象都会在块的末尾超出范围,并调用其析构函数。copyscopys{}