【问题标题】:Memory Management with returning char* function带返回 char* 函数的内存管理
【发布时间】:2011-05-30 21:34:31
【问题描述】:

今天,我不假思索地写了一个简单的函数返回一个 char* 基于给定枚举值的 switch 语句。然而,这让我想知道如何才能释放那段记忆。我所做的是这样的:

char* func()
{
    char* retval = new char[20];
    // Switch blah blah - will always return some value other than NULL since default:
    return retval;
}

如果这是一个幼稚的问题,我深表歉意,但是释放内存的最佳方法是什么.我认为可行的解决方案是这样的

void func(char*& in)
{
    // blah blah switch make it do something
}

int main()
{
    char* val = new char[20];

    func(val);
    // Do whatever with func (normally func within a data structure with specific enum set so could run multiple times to change output)

    delete [] val;
    val = NULL;
    return 0;
}

是否有人对此有更多见解和/或解释如何使用?

问候,
丹尼斯 M.

【问题讨论】:

  • 您的第二个代码示例没有任何意义。您在 void 函数中返回,将字符值分配给指针,引用指针(有效但不经常有用)。
  • 对不起,错字。应该没有回报。
  • 顺便说一句,如果你返回一个char *,我想你需要返回一个字符串而不是单个字符,在这种情况下你应该使用new char[size]/delete []
  • 是的,对于第二个示例中的拼写错误,我深表歉意。我在发这篇文章的时候写的很简短,没有仔细检查。
  • @Raged :还有问题。这不是错字。就是你不知道val = NULL;之前delete val;没有意义!

标签: c++ windows linux compiler-construction memory-management


【解决方案1】:

在这种情况下,调用 func() 的人应该在不需要时释放内存。但是正确的删除是这样发生的:

delete val;
val = NULL;

【讨论】:

    【解决方案2】:

    您是否考虑过使用 STL 类型或其他类而不是返回原始指针?例如,如果您的 char * 是一个字符串,请改用 std::string 并避免任何泄漏风险:

    std::string func()
    {
        std::string retval("");
    
        // Switch blah blah - will always return some value other than NULL since default:
    
        return retval;
    }
    

    【讨论】:

      【解决方案3】:

      你可以成对编写这样的函数,比如

      Xyz* CreateXyz();
      void DestroyXyz(Xyz *xyz);
      
      
      Abc* NewAbc();
      void DeleteAbc(Abc *abc);
      

      或者您可以简单地将删除 Xyz/Abc 的责任转移给客户端,即调用该函数的人还必须在使用它后对返回的对象执行delete

      无论您选择什么,请在文档中明确说明创建的对象应如何销毁。

      我更喜欢配对函数,特别是如果在删除之前需要考虑很多事情!

      顺便说一句,您应该更喜欢使用std::string,而不是char*。尽可能多地使用 STL。他们可以解决您的大部分问题!以上建议适用于 STL 不适合的情况!一般来说,更喜欢 STL!

      【讨论】:

      • 谢谢!我确实经常使用 STL,但是,我只是想知道在这种情况下如何进行这项工作。很棒的解决方案。
      • 我要补充一点,创建一个类来保存资源(并在析构函数中释放它)通常会更好。所以创建 XYZ 和 ABC 类,而不是为它们创建新/删除函数。
      • @Winston Ewert:这也很好。但是如果一个人创建了使用和抛出类型的对象并且过于频繁,那么最好在您的设计中使用配对功能(如我的帖子中所述),以便用户可以在使用后立即销毁对象。
      • @Nawaz,我不确定你的意思是使用并抛出。我假设您的意思是您创建对象,在短时间内使用它,然后摆脱它。 (我建议 throw 不是一个好的术语选择,因为 throwing 用于异常。)但是,在这种情况下,我想在我的堆栈上创建一个对象,以便在函数结束时自动销毁它。我没有看到在那里使用配对函数会更好。
      • @Winston Ewert:如果他想从函数中返回对象,在这种情况下,配对函数是有意义的。这是另一种情况:stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/…
      【解决方案4】:

      如果您打算从函数返回原始指针,您必须在文档中明确说明删除指针的责任,即谁拥有它。在这种情况下,您应该明确声明指针所有权转移给调用者,调用者负责delete它。

      虽然很多人都可以在文档中指定所有权,但通常最好在代码中强制执行此策略。特别是,智能指针经常用于此目的:当前的 C++ 标准提供了std::auto_ptr,这是一个在副本上转移所有权的智能指针,即当你将它返回给调用者时,你正在转移目标std::auto_ptr 的所有权。请注意,std::auto_ptr 自动 deletes 指向的内存在其销毁时仍然拥有它。即将推出的 C++ 标准提供了 std::unique_ptr,其工作方式类似,但使用移动语义。

      不幸的是,std::auto_ptr 不适用于数组(需要delete [] 而不是delete),因此您不能将其用于您的目的。我认为不包含数组的auto_ptr 的决定是故意的,因为如果您需要返回由它们自己的内存管理和复制处理的项目集合,STL 已经提供了您可能需要的所有容器。

      特别是对于字符串,您应该简单地使用std::string,而完全忘记这种内存管理和指针所有权问题。

      【讨论】:

        猜你喜欢
        • 2020-09-21
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        • 2011-09-28
        • 1970-01-01
        • 2012-06-15
        相关资源
        最近更新 更多