Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
显式调用析构函数时被调用两次 我在C++中用析构函数对这段代码进行了实验: #include <iostream> struct temp { ~temp() { std::cout << "Hello!" << std::endl; } }; int main() { temp t; t.~temp(); } #包括 结构温度 { ~temp(){std::cout_C++_Destructor - Fatal编程技术网

显式调用析构函数时被调用两次 我在C++中用析构函数对这段代码进行了实验: #include <iostream> struct temp { ~temp() { std::cout << "Hello!" << std::endl; } }; int main() { temp t; t.~temp(); } #包括 结构温度 { ~temp(){std::cout

显式调用析构函数时被调用两次 我在C++中用析构函数对这段代码进行了实验: #include <iostream> struct temp { ~temp() { std::cout << "Hello!" << std::endl; } }; int main() { temp t; t.~temp(); } #包括 结构温度 { ~temp(){std::cout,c++,destructor,C++,Destructor,它之所以发生,是因为你告诉它发生。当变量超出范围时,总是调用自动变量的析构函数。你也调用了它。总共调用了两次 调用对象的析构函数不向C++发出信号,不调用它,因为在正常执行中不需要跟踪。 解决方法是永远不要手动调用析构函数。调用析构函数不会释放对象 析构函数用于清理对象的内部,然后在析构函数完成后释放对象本身 这样做是错误的,类似于对对象调用delete两次,但这样做是错误的 只有极少数情况下,您需要手动调用析构函数,但这不是其中之一。它确实适用于您使用placement new在内存位置手动构

它之所以发生,是因为你告诉它发生。当变量超出范围时,总是调用自动变量的析构函数。你也调用了它。总共调用了两次

调用对象的析构函数不向C++发出信号,不调用它,因为在正常执行中不需要跟踪。


解决方法是永远不要手动调用析构函数。

调用析构函数不会释放对象

析构函数用于清理对象的内部,然后在析构函数完成后释放对象本身

这样做是错误的,类似于对对象调用delete两次,但这样做是错误的


只有极少数情况下,您需要手动调用析构函数,但这不是其中之一。它确实适用于您使用placement new在内存位置手动构造对象,然后需要能够在不释放内存的情况下对其进行析构函数。

您不应该实际调用析构函数。它被称为因此,您只需调用一次,运行时支持将第二次调用它

以下是一些关于析构函数的思考:


您可以显式调用解构器,但不建议这样做,通常它们是隐式调用的。

如果不显式调用析构函数,则当变量超出范围时会自动调用它(在
return 0;
语句之后)。这就是为什么会调用它两次,您调用它,然后系统调用它的原因

如果您希望自己能够明确地删除此类的实例,则需要动态分配它:

temp *t = new temp;     
// do stuff with t...
delete t;    // do not forget this, or the constructor is not being called at all

如果对象在堆栈中(如本例中),则当对象超出范围时调用析构函数;如果对象在堆上以new运算符首先创建对象,则当使用delete显式析构函数时调用析构函数

编译器或运行时系统无法跟踪您是否手动调用析构函数。调用析构函数也是一种非常糟糕的做法

如果要在删除对象之前进行一些手动清理(而不是从内存中删除对象或从堆栈中删除对象),可以执行以下操作

在这里,您希望允许客户端手动清理对象,即使在对象被删除之前也是如此。但除此之外,如果客户端未能清理对象,您也可以进行清理

class A
{
public:
    A() : _closed(false)
    {}

    ~A()
    {
        close();
    }

    void close()
    {
        if (! _closed()) {
            // close file handles etc.
        }
    }

private:
    bool _closed
}
我看到“Hello!”被打印了两次。析构函数的调用不应该释放对象,并且当它超出范围时不应该再次调用析构函数。或者有其他概念吗

没错

我必须指出,我并不打算在实践中这样做,我只是想了解这里发生了什么

您已经调用了析构函数,准备要销毁的对象。但当对象超出范围时,在实际取消分配之前,也会自动执行此操作


要理解的是:如果你做了没有意义的事情,那么坏事就会发生。所以不要做没有意义的事情。如果你手动调用析构函数,那么析构函数就会运行。这对其他任何事情都没有影响,除非析构函数真的做了一些有影响的事情。

你只需调用析构函数,就不会执行任何操作在逻辑上释放任何内存(它是静态分配的)。如果使用new然后delete,析构函数将只调用一次。

析构函数不是对象的“破坏者”。它只是一个普通函数,但在销毁之前语言会自动调用它


它的正式名称是毁灭者,但如果我们称之为“毁灭前”,它可能更容易理解函数。

您不需要调用析构函数,尽管可以这样做。当对象不再使用时,编译器应该隐式地为您运行析构函数。创建对象时,如果已使用类成员的特定和初始化值声明该对象,则会为该对象使用构造函数。当不再需要您的对象,析构函数将运行和删除成员变量声明及其值。这对于不使用自动垃圾收集的语言来说是最有用的,例如C++。

类的析构函数可以调用:

  • 明确地

    当使用类的对象显式调用析构函数时,与调用该类的另一个成员函数的方式相同

  • 隐式地

    当类的对象超出范围或使用新操作符创建的对象使用delete操作符销毁时

  • 在示例程序中,您可以同时执行这两项操作

    int main()
    {
      temp t;
    
      t.~temp(); //1. Calling destructor explictly using the object `t`
    
      return 0;
    } // 2. object `t` goes out of scope. So destructor invoked implictly
    
    这就是为什么你会看到析构函数被调用了两次


    正如您所想,析构函数将销毁构造函数创建的资源。因此不应显式调用析构函数,因为它将导致销毁已销毁的资源,这可能是致命的。

    好的。但是,当我第一次调用它时,它不应该取消分配对象,第二次调用应该ead是否存在seg故障?否。该对象是自动的,不是动态的。这意味着它没有分配到可以解除分配的位置(在大多数系统上,它位于堆栈而不是堆上)由于您的对象是自动分配的,并且没有动态分配的字段,因此在其作用域的末尾它仍然是完全形成的。这是高度特定于实现的行为,决不能依赖。@Cygnus:它会导致未定义的行为。@Inverse:是的,根据:<