繁体   English   中英

析构函数如何在c ++中工作

[英]how the destructor works in c++

这是我的c ++代码:

  class Sample
    {
    public:
            int *ptr;
            Sample(int i)
            {
            ptr = new int(i);
            }
            ~Sample()
            {
            delete ptr;
            }
            void PrintVal()
            {
            cout << "The value is " << *ptr;
            }
    };
    void SomeFunc(Sample x)
    {
    cout << "Say i am in someFunc " << endl;
    }
    int main()
    {
    Sample s1= 10;
    SomeFunc(s1);
    s1.PrintVal();
    }

它返回我的输出,如:

Say i am in someFunc 
Null pointer assignment(Run-time error)

这里,当对象通过值传递给SomeFunc时,控件从函数返回时会调用该对象的析构函数

我应该对吗? 如果是,那为什么会发生? 什么解决方案?

由于你有一个指针成员,你通常需要遵守三法则
在您的代码示例中,为了避免您看到的未定义行为:

通过必须先声明更换需要

Sample通过值传递给SomeFunc ,这意味着要进行复制。 副本具有相同的ptr ,因此当SomeFunc返回时销毁该副本时,将删除两个对象的ptr 然后,当您在main中调用PrintVal() ,您将取消引用此无效指针。 这是未定义的行为。 即使有效,那么当s1被破坏时, ptr也会被删除,这也是UB。

此外,如果编译器未能删除Sample s1= 10;的副本Sample s1= 10; 然后s1甚至无法开始有效,因为当临时被销毁时,指针将被删除。 大多数编译器确实避免使用此副本。

您需要正确实现复制或禁止复制。 此类型的默认copy-ctor不正确。 我建议将此类型设置为值类型(直接保存其成员而不是指针),以便默认的copy-ctor可以工作,或者使用智能指针来保存引用,以便它可以管理引用资源您和默认的copy-ctor仍然有效。

我真正喜欢C ++的一个原因是它对于在任何地方使用值类型都非常友好,如果你需要一个引用类型,你可以在智能指针中包装任何值类型。 我认为这比具有值语义的原始类型的其他语言更好,但是用户定义的类型默认具有引用语义。

由于SomeFunc()按值获取其参数,因此将传递传递给它的Sample对象。 SomeFunc()返回时,临时副本将被销毁。

由于Sample没有定义复制构造函数,因此其编译器生成的复制构造函数只是复制指针值,因此两个Sample实例都指向相同的int 当一个Sample (临时副本)被销毁时,该int被删除,然后当第二个Sample (原始)被销毁时,它会再次尝试删除相同的int 这就是你的程序崩溃的原因。

您可以更改SomeFunc()以获取引用,避免临时副本:

void someFunc(Sample const &x)

和/或您可以为Sample定义一个复制构造函数,它分配一个新的int而不是仅仅将指针复制到现有的指针。

当您传递函数的参数时,它被称为复制构造函数,但是您没有它,因此指针未初始化。 当它退出函数时,对象调用析构函数来删除单元化指针,因此它会产生错误。

代替

int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
}

试着用

int main()
{
Sample* s1= new Sample(10);
SomeFunc(*s1);
s1->PrintVal();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM