gpt4 book ai didi

c++ - 为什么在这种情况下只调用一个构造函数而调用两个析构函数?

转载 作者:搜寻专家 更新时间:2023-10-31 00:56:29 25 4
gpt4 key购买 nike

第一次,代码如下:

#include "stdafx.h"
#include<iostream>
using namespace std;

class Test{
public:
explicit Test(int);
~Test();
//Test(Test&);
int varInt;
};
Test::Test(int temp){
varInt = temp;
cout << "call Test::constructor\n";
}
Test::~Test(){
cout << "call Test::destructor\n";
}
/*Test::Test(Test&temp){
varInt = temp.varInt;
cout << "call Test::copy constructor\n";
}*/
void func(Test temp){
cout << "call func\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
func(Test(1));
return 0;
}

输出:

call Test::constructor
call func
call Test::destructor
call Test::destructor

这让我很困惑,因为只创建了一个对象(作为 func 的参数),但是在函数结束后调用了两个析构函数。我开始怀疑,这是因为调用了默认的复制构造函数吗?所以我写了复制构造函数的定义,这让事情变得更加奇怪。在我将上面看到的注释掉的代码,即复制构造函数的定义添加到类中之后,输出变成了这样:

输出:

call Test::constructor
call func
call Test::destructor

事情变得恰到好处。谁能给我解释一下这个现象?非常感谢。

最佳答案

  • 您对原始代码的解释(调用隐式声明的复制构造函数)是正确的。
    • 根据您的编译器执行的标准版本,它实际上可能使用隐式声明的移动构造函数。但这相当于同一件事。
  • 您修改后的代码(您明确提供了复制构造函数的地方)恰好触发了 the copy elision optimization ,编译器只是在所需位置开始构建对象。这是标准明确允许优化的少数情况之一,即使它会影响程序的可观察行为(因为您可以判断是否调用了复制构造函数)。
  • 您修改后的代码不需要复制省略,您的原始代码也禁止它;这两个版本恰好不同,它们是否会在当前设置下触发编译器中的优化。
    • 注意:这里的情况在 C++17 中略有变化,在某些情况下这种优化确实成为强制性的。有关详细信息,请参阅我上面的链接。

编辑添加:顺便说一句,在您的带有显式复制构造函数的版本中,您的构造函数在采用非常量 引用方面是不寻常的。这实际上意味着无论如何都不能使用它,因为非常量引用不能绑定(bind)到临时 Test(1)。我认为这种奇怪现象可能与您的编译器执行复制省略的原因有关。如果您将构造函数更改为采用常量 引用,就像隐式声明的复制构造函数那样,您可能会看到预期的行为,即显式复制构造函数被调用并且析构函数被调用两次。 (但这只是我的猜测;您必须尝试看看!)

关于c++ - 为什么在这种情况下只调用一个构造函数而调用两个析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39462412/

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