当变量仍然存在时调用C++析构函数
C++ Destructor being called when variable still alive
我有一个类,它有一个指向整数的指针。
然后是一个静态函数,它将返回该整数的值。
我注意到,当调用静态函数时,每次都会为该对象调用析构函数。
我不明白为什么会发生这种行为。
class Dog
{
public:
Dog(int val){
this->pVal = new int(val);
}
~Dog(){
delete this->pVal;
}
static int GetVal(Dog d){
return *(d.pVal);
}
int *pVal;
};
这就是课堂。
这是我的测试驱动程序代码。
Dog fido(20);
std::cout << Dog::GetVal(fido); //20 and destructor for fido called
Dog rex(21);
std::cout << Dog::GetVal(fido); //21 but should be 20
std::cout << Dog::GetVal(rex); // should be 21
我注意到两个dog对象都位于不同的内存地址,但int指针位于相同的地址。我相信这是因为在调用GetVal时调用了fido的析构函数,但我不知道为什么会发生这种行为。
虽然确实调用了"Fido"的析构函数,但这不是原始的"Fido",而是它的副本。您的GetVal(Dog d)
函数按值取Dog
,这意味着"Fido"在传递给GetVal
之前被复制,然后副本在完成时被销毁。
通过const
引用传递Dog&
可以修复此问题:
static int GetVal(const Dog& d){
return *(d.pVal);
}
演示。
注意:以上并不能解释为什么你在"Fido"中获得21分。由于您没有定义复制构造函数或赋值运算符,因此编译器为您生成了一个简单的复制构造函数。因此,"Fido"副本中的pVal
与原始"Fido》中的pVal
指向相同的位置。从Dog::GetVal(fido)
返回后,一旦副本被销毁,内存就有资格重用,并且原始"Fido"中的指针就会悬空。当您第二次调用Dog::GetVal(fido)
时,该函数会通过取消引用悬挂指针来导致未定义的行为。第二个调用打印21,即您传递给"Rex"构造函数的值,这一事实强烈表明,销毁"Fido"副本时释放的内存在构建"Rex》时会立即被重用。但是,C++不需要这样做。如果发生这种情况,当"Rex"answers"Fido"在运行结束时被销毁时,您的代码将第二次导致UB。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用