gpt4 book ai didi

c++ - 为什么析构函数被执行了两次?

转载 作者:行者123 更新时间:2023-12-01 19:59:54 25 4
gpt4 key购买 nike

#include <iostream>
using namespace std;

class Car
{
public:
~Car() { cout << "Car is destructed." << endl; }
};

class Taxi :public Car
{
public:
~Taxi() {cout << "Taxi is destructed." << endl; }
};

void test(Car c) {}

int main()
{
Taxi taxi;
test(taxi);
return 0;
}

这是输出:

Car is destructed.
Car is destructed.
Taxi is destructed.
Car is destructed.

我使用MS Visual Studio Community 2017(抱歉,我不知道如何查看Visual C++的版本)。当我使用 Debug模式时。我发现离开 void test(Car c){ } 时会执行一个析构函数。函数体如预期的那样。当 test(taxi); 时,会出现一个额外的析构函数。结束了。

test(Car c)函数使用值作为形式参数。前往该功能时会复制汽车。所以我以为离开该功能时只会有一个“汽车被破坏”。但实际上在离开该函数时有两个“Car is destructed”。(第一行和第二行如输出所示)为什么有两个“汽车被毁”?谢谢。

==============

当我在 class Car 中添加虚拟函数时例如:virtual void drive() {}然后我得到预期的输出。

Car is destructed.
Taxi is destructed.
Car is destructed.

最佳答案

看起来 Visual Studio 编译器在为函数调用切片 taxi 时采取了一些捷径,具有讽刺意味的是,这导致它完成的工作比预期的要多。

首先,它会获取您的taxi并从中复制构造Car,以便参数匹配。

然后,它再次复制 Car 以进行值传递。

当您添加用户定义的复制构造函数时,这种行为就会消失,因此编译器似乎是出于自己的原因(也许在内部,这是一个更简单的代码路径)这样做,利用了“允许”的事实因为拷贝本身是微不足道的。事实上,您仍然可以使用非平凡的析构函数观察到这种行为,这有点反常。

我不知道这在多大程度上是合法的(特别是自 C++17 以来),或者为什么编译器会采用这种方法,但我同意这不是我的输出会直觉地预期。 GCC 和 Clang 都没有这样做,尽管它们可能以相同的方式做事,但更擅长省略拷贝。我已经注意到,即使是 VS 2019 在保证消除方面仍然不是很好。

关于c++ - 为什么析构函数被执行了两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58579523/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com