下面的结果是非常有趣的,我有困难,了解他们。 基本上我有它有一个int类:
class TestClass{
public:
int test;
TestClass() { test = 0; };
TestClass(int _test) { test = _test; };
~TestClass() { /*do nothing*/ };
};
的测试功能,它接受的TestClass的指针
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
这是我在主正在做的:
int main(int argc, _TCHAR* argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
return 0;
}
我期待输出是:
test before: 1
test in testFunction1: 2
test after: 1
但我得到下面的输出:
test before: 1
test in testFunction1: 2
test after: 2
有人可以解释这一点。 有趣的是,改变testFunction1到:
void testFunction1(TestClass *ref){
//delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
也就是说,我不将其指向新的位置之前删除裁判,我得到下面的输出:
test before: 1
test in testFunction1: 2
test after: 1
我真的很感激,如果有人可以解释我的这种奇怪的行为。 谢谢。
当你在删除后访问该对象,则行为未定义。
您看到的行为,从系统中的内存分配算法如下。
这就是删除您第一TestClass的对象之后,你对新对象分配内存。 运行时只是重用的内存。
要检查是怎么回事,打印指针的值:
void testFunction1(TestClass *ref){
cout << ref << endl;
delete ref;
TestClass *locTest = new TestClass();
cout << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
你得到的指针的副本中的对象testFunction1()
所以当你分配给它,在指针的初始值main()
没有变化
此外,要删除的对象(通过调用delete
在testFunction1()
到原来的指针(在main()
指向,但作为价值main()
不更新,您正在访问一个无效的对象-事实上,你可以读取您在设置的值testFunction1()
是一个巧合,不能依靠
您正确在第二种情况下读取原始值(当你不叫事实上delete
),是因为原来的对象没有被改变(你改变一个新的testFinction1
和指针,它main
是相同的(如上文所解释)和对象仍然活着
在这种情况下,你刚在与旧删除同一地址的新对象。
实际上testObj成了一个悬摆指针调用testFunction1后。
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
cout << "locTest = " << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
int main(int argc, char * argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
return 0;
}
输出是:
test before: 1
testObg = 0x511818
locTest = 0x511818
test in testFunction1: 2
test after: 2
testObg = 0x511818
该指令后:
TestClass *testObj = new TestClass(1);
你分配包含一个新的内存区域TestClass
对象,其地址(姑且称之为maddr
)存入testObj
。
现在,这个指令:
cout << "test before: " << testObj->test << endl;
输出1
,如所预期。
内部testFunction1()
你有称为本地变量ref
,这是包含值的指针maddr
。
当你delete ref
,取消分配的包含内存区域TestClass
对象,其地址为maddr
。
然后你分配一个新的内存区域:
TestClass *locTest = new TestClass();
和locTest
包含其地址,让我们称之为m1addr
。
然后使用ref
在访问内存区域m1addr
和改变int test
值为2
。
该指令:
cout << "test in testFunction1: " << ref->test << endl;
输出2
按预期方式。
现在,回到main
,你已经失去了任何处理程序包含区域TestClass
对象,其地址为m1addr
(也就是你正在泄漏内存)和区域指向testObj
不再被分配。
当您使用testObj
再次,您访问的存储器中,起始面积maddr
,这已被清理。 访问的效果testObj->test
是不确定的行为。
您遇到什么可以做这样一个事实,当你运行你的代码maddr == m1addr
,但是这只能是偶然发生的,你不能靠这个。
奇怪的是正在创建新的对象(具有2)其中,旧的已删除对象(具有1)曾经是。 您的原始指针仍指向该位置,所以当你访问你不小心访问新对象(2)。
TestClass的*裁判在主要的参数testFunction1和识别TestClass * testObj是2个不同的指针指向同一件事,他们是不一样的指针虽然。 如果你想给一个函数/方法内删除并重新分配一个对象,你可以使用指针的指针作为参数。
正如其他人所说,你所访问这是内testfunction1其作为也提到删除的对象后testfunction1是不确定的行为。 内存被指向的悬摆指针是在删除释放,但内容可能依然存在,直到存储位置被再次调用新过程中重新分配。 所以,你正在使用,可以在任何时候很容易被覆盖的未分配空间。
希望这可以帮助