【问题标题】:Declaring a pointer inside a function, C++在函数内声明一个指针,c ++
【发布时间】:2021-05-16 10:02:36
【问题描述】:

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

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

【问题讨论】:

标签: c++11 pointers


【解决方案1】:

您编写的代码会泄漏。

==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;

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

【讨论】:

    【解决方案2】:

    动态分配的对象在被释放或“释放”之前一直存在。这正是动态分配的目的:创建其生命周期不依赖于范围的对象(即,不会在下一个右花括号结束,如自动变量)但也不是无限的,如全局或静态变量。相反,动态分配对象的生命周期完全由在运行时“动态”决定。

    返回指向动态分配对象的指针是一种常见模式,例如factory functions

    Jacob 是正确的,您的程序没有释放分配的对象。在程序结束之前的某个时间释放所有资源(这包括打开的文件和套接字以及系统资源的其他句柄)是一种很好的风格。但这会有什么不同吗?不,因为all operating systems clean up the memory after program termination(同时链接的答案使得清理无论如何 :-) 的理由)。您的程序可以运行任意多次,而不会耗尽内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 2016-08-04
      相关资源
      最近更新 更多