在函数内部声明指针,c++



当我在函数内部注册一个新的指针时会发生什么?我承认,指针的名字应该被销毁。但是分配的内存怎么办呢?它会是内存泄漏吗?在我的示例中,数据对象在函数终止后是否仍然有效,或者它只是偶然工作,在更复杂的实例中容易出现未定义的行为?在这个例子中删除应该放在哪里?或者应该避免这种写作方式?

int * one (void);
int main (void){
int *two = new int;
*two = *one ();
cout << "Address: " << one() << "|" << *one() << endl; // Address: 0xe51a78|5555
cout << "Address: " << two << "|" << *two << endl;  // Address: 0xe519d8|5555
}
int * one (void){
int * pFun = new int; // declaration of a pointer inside a function
*pFun = 5555;
return pFun;
}

你写的代码会泄漏。

==365== Memcheck, a memory error detector
==365== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==365== Using Valgrind-3.17.0.GIT and LibVEX; rerun with -h for copyright info
==365== Command: ./test
==365== 
==365== 
==365== HEAP SUMMARY:
==365==     in use at exit: 8 bytes in 2 blocks
==365==   total heap usage: 3 allocs, 1 frees, 72,712 bytes allocated
==365== 
==365== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2
==365==    at 0x484D103: operator new(unsigned long) (vg_replace_malloc.c:342)
==365==    by 0x10919E: main (in /petsc/test)
==365== 
==365== 4 bytes in 1 blocks are definitely lost in loss record 2 of 2
==365==    at 0x484D103: operator new(unsigned long) (vg_replace_malloc.c:342)
==365==    by 0x1091CC: one() (in /petsc/test)
==365==    by 0x1091A7: main (in /petsc/test)
==365== 
==365== LEAK SUMMARY:
==365==    definitely lost: 8 bytes in 2 blocks
==365==    indirectly lost: 0 bytes in 0 blocks
==365==      possibly lost: 0 bytes in 0 blocks
==365==    still reachable: 0 bytes in 0 blocks
==365==         suppressed: 0 bytes in 0 blocks
==365== 
==365== For lists of detected and suppressed errors, rerun with: -s
==365== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

注意,上面我删除了两个打印调用,因为第一个调用one()两次以上,导致2个额外的泄漏

不直接存储one()返回的指针,而是立即对其解引用。这样做的效果是抛出那个地址。一个更好的方法是这样做:

// two is an uninitialized pointer
int *two;
// Assign the returned pointer to two
two = one();
// Assign the value pointed to by two (and in effect one()) to three and use it
int three = *two;
functionThatExpectsAnInt(three);
// Alternatively use two directly, it points to valid memory whose value has not changed
functionThatExpectsAnInt(*two);
// Clean up resources from one()
delete two;

对于返回分配内存的函数,调用者是有效的"所有者"。函数返回的资源的。因此,调用者要么释放资源,要么将它们传递给另一个函数。

动态分配的对象一直存在,直到它被取消分配或"释放"。这正是动态分配的目的:创建的对象的生命周期不依赖于作用域(也就是说,不像自动变量那样在下一个结束大括号处结束),但也不是无限的,像全局变量或静态变量那样。相反,动态分配对象的生存期完全是在运行时决定的,&;动态地&;

返回动态分配对象的指针是一种常见的模式,例如工厂函数。

Jacob说你的程序没有释放分配的对象是对的。在程序结束前的某个时间点释放所有资源(包括打开的文件、套接字和其他对系统资源的句柄)是一种很好的方式。但这有什么区别吗?不,因为所有的操作系统都会在程序终止后清理内存(同时链接的答案也会清理:-))。你的程序可以正常运行,你想运行多少次就运行多少次,而不会耗尽内存。

最新更新