临时对象未正确销毁
Temporary object not destroyed correctly?
请在此处查看此代码:
class test
{
int n;
int *j;
public:
test(int m)
{
n = 12;
j = new int;
cin >> *j;
}
void show()
{
cout << n << ' ' << *j << endl;
}
~test()
{
delete j;
}
};
int main()
{
test var = 123;
var.show();
return 0;
}
在这个程序中,编译器应该抱怨j
的双重删除。当临时对象temporary(123)
被破坏时,进行第一次删除。第二次删除是在var
对象被破坏时完成的。但这还可以吗?
这是否意味着临时对象不调用析构函数
有争议的一句话是:
test var = 123;
我相信,相关的标准文本(评论中的专家们引用的)是(8.5,"声明人"):
调用所选函数时,将初始值设定项表达式作为其参数;如果函数是一个构造函数,则调用会初始化目标类型的cv非alified版本的临时版本。临时值是一个值。调用的结果(对于构造函数来说是临时的)然后用于根据上面的规则直接初始化作为复制初始化目标的对象。在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制;
事实上,在12.6中,我们得到了一个例子:
complex f = 3; // construct complex(3) using
// complex(double)
// copy it into f
因此,在使用=
时,您的实现可能是直接构建对象并完全消除中间临时对象(正如注释所指出的,大多数都是这样做的)。
这个类没有正确复制,所以创建它的副本(以及释放副本和原始副本)会导致双重删除(以及崩溃、未定义的行为等)。因为没有创建副本,所以上面不会发生这种情况。
两点:首先,在这种特殊情况下,允许编译器通过对标准我熟悉的所有编译器都有。你可以验证是否通过定义复制构造函数在代码中发生这种情况
第二,如果临时的没有优化,你的代码未定义的行为。双重删除可以有任何可以想象的行为:立即崩溃,自由空间竞技场的腐败(导致如果程序继续运行,很晚就会崩溃),没有效果永远,或其他任何事情。事实上,你没有看到任何症状并不意味着代码是正确的。
代码没有爆炸并不意味着它是正确的。
您的类有缺陷,因为它很容易受到您所描述的双deletes
的影响。
例如,将var.show();
更改为以下内容:
test(var).show();
使代码在我的计算机上可靠地爆炸。
若要修复此问题,请实现复制构造函数和赋值运算符。
- 在不复制临时对象的情况下延长其生存期
- 为什么当我们有常量引用时创建临时对象?
- 程序如何'remember'临时对象?
- 返回对临时对象的引用
- 防止临时对象文件访问 MSVC 中的磁盘
- 是否可以在C++中移动临时对象的属性?
- 通过引用传递临时对象
- 临时C++对象是否为左值?
- 临时对象:术语澄清
- 存储对(可能)临时对象的引用是否合法,只要引用不比对象存活?
- 临时对象有身份吗?
- 临时对象上的运算符重载
- 如何在没有 std::move 的情况下移动临时对象
- 临时对象在C++中是不可避免的吗?
- 编译错误:临时对象构造函数中缺少参数
- 为什么在按值返回时创建临时对象,而不是在按值传递给函数参数时创建临时对象
- 我试图创建临时对象的方式有错误吗
- 子表达式中临时对象的生存期
- 对临时对象的Const引用不会延长其生存期
- 为什么引用类型在使用临时对象访问时是左值