在C指针的奇怪行为++(Strange behavior of pointers in c++)

2019-06-24 16:12发布

下面的结果是非常有趣的,我有困难,了解他们。 基本上我有它有一个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

我真的很感激,如果有人可以解释我的这种奇怪的行为。 谢谢。

Answer 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;
}


Answer 2:

你得到的指针的副本中的对象testFunction1()所以当你分配给它,在指针的初始值main()没有变化

此外,要删除的对象(通过调用deletetestFunction1()到原来的指针(在main()指向,但作为价值main()不更新,您正在访问一个无效的对象-事实上,你可以读取您在设置的值testFunction1()是一个巧合,不能依靠

您正确在第二种情况下读取原始值(当你不叫事实上delete ),是因为原来的对象没有被改变(你改变一个新的testFinction1和指针,它main是相同的(如上文所解释)和对象仍然活着



Answer 3:

在这种情况下,你刚在与旧删除同一地址的新对象。

实际上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


Answer 4:

该指令后:

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 ,但是这只能是偶然发生的,你不能靠这个。



Answer 5:

奇怪的是正在创建新的对象(具有2)其中,旧的已删除对象(具有1)曾经是。 您的原始指针仍指向该位置,所以当你访问你不小心访问新对象(2)。



Answer 6:

TestClass的*裁判在主要的参数testFunction1和识别TestClass * testObj是2个不同的指针指向同一件事,他们是不一样的指针虽然。 如果你想给一个函数/方法内删除并重新分配一个对象,你可以使用指针的指针作为参数。

正如其他人所说,你所访问这是内testfunction1其作为也提到删除的对象后testfunction1是不确定的行为。 内存被指向的悬摆指针是在删除释放,但内容可能依然存在,直到存储位置被再次调用新过程中重新分配。 所以,你正在使用,可以在任何时候很容易被覆盖的未分配空间。

希望这可以帮助



文章来源: Strange behavior of pointers in c++