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

Mil*_*ara 4 c++ oop destructor

这是我的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();
    }
Run Code Online (Sandbox Code Playgroud)

它返回我的输出,如:

Say i am in someFunc 
Null pointer assignment(Run-time error)
Run Code Online (Sandbox Code Playgroud)

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

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

Alo*_*ave 5

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

更换需要在第一条语句必须.


bam*_*s53 5

Sample按值传递SomeFunc,表示复制.副本具有相同的ptr,因此当SomeFunc返回时销毁该副本时,ptr将删除这两个对象.然后当您PrintVal()在main中调用时,取消引用此无效指针.这是未定义的行为.即使是工作那么当s1被销毁ptr又被删除,这也是UB.

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

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

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