【问题标题】:C++ management of strings allocated by a literal由文字分配的字符串的 C++ 管理
【发布时间】:2011-04-21 20:32:17
【问题描述】:

我是否需要处理由文字分配的 C++ 字符串的内存分配、范围和删除?

例如:

#include <string>

const char* func1() {
    const char* s = "this is a literal string";
    return s;
}

string func2() {
    std::string s = "this is a literal string";
    return s;
}

const char* func3() {
    std::string s = "this is a literal string";
    return s.c_str();
}

void func() {
    const char*  s1 = func1();
    std::string s2 = func2();
    const char*  s3 = func3();

    delete s1; //?
    delete s3; //?
}
  • func2:我不需要delete s2
  • func3:需要delete s3吗?

func1 正确吗?字符记忆内容离开func1 的范围后是否仍然可用?如果是的话,当我不再需要它时,我应该删除它吗?

【问题讨论】:

标签: c++ string memory


【解决方案1】:

您对 s3 有一个不同的问题,即函数 func3() 返回指向对象的指针,该对象在函数返回时超出范围。不要。

澄清:您在 func3() 中的本地字符串对象将在函数返回时不复存在,因此无需删除。但是,您仍然有一个指向您返回的内部缓冲区的指针。你不能用那个。

非常好的和详细的过去答案,以免引起更多混乱:Is it more efficient to return a const reference

【讨论】:

  • @Alexander Rautenberg - 最好让他使用 s3 的引用,而不是指针。无论如何它都是正确的。
  • 如果使用指针或引用,func3() 或 s3 的问题仍然相同。 func3() 的编码方式没有任何正确之处。
  • @Alexander Rautenberg - 如果检查正确,则不在参考中,对于字符串。返回一个对象但将它绑定到一个 const 对象会增加它的生命周期,直到程序退出。如果他返回一个字符串而不是一个 char 指针,他很好。
  • @DumbCoder 如果他返回一个 std::string,他很好,同意。但我认为最初的问题是关于在不同情况下使用带指针的 delete,这就是 func3() 无法适应的地方。
【解决方案2】:
  • func1() 返回一个指向字符串文字的指针。您不得删除字符串文字。
  • func2()(大概是您省略了std:: 前缀)返回std::string。它会照顾好自己。
  • func3() 返回一个指向由 std::string 对象管理的字符串的指针,该对象在函数退出时被销毁。函数返回后,您不得触摸该指针。
  • 您必须注意此函数返回的内存:

    const char* func4() {
       char* s = new char[100];
       // fill char array with a string
       return s;
    }
    

但是,手动资源管理很棘手。对于初学者,如果一个函数返回一个裸指针,您不知道它是指向一个对象 (char) 还是其中的一个数组,以及是否需要删除它。您应该避免所有这些,并坚持使用std::string

【讨论】:

    【解决方案3】:

    我将每个函数的相关代码和其返回值的处理都剪掉了,并在下方评论:

    const char* func1() {
       const char* s = "this is a literal string";
       return s;
    }
    const char*  s1 = func1();
    delete s1; //?
    

    你不能删除s1,因为它指向的字符串不在堆上。

    string func2() {
       string s = "this is a literal string";
       return s;
    }
    string s2 = func2();
    

    这很好。 func2s 超出范围并进行清理。 s2 将复制来自s 的字符串,并在func 的末尾自行清理。

    const char* func3() {
       string s = "this is a literal string";
       return s.c_str();
    }
    const char*  s3 = func3();
    delete s3; //?
    

    func3 返回一个指向已释放字符串的指针。执行delete s3 时,您将获得双重免费异常。

    【讨论】:

      【解决方案4】:

      在 func3 中,您的字符串 local 是由编译器调用隐式构造函数 string(const char*) 使用字符串文字的副本初始化其内部缓冲区创建的。然后,您返回一个指向字符串内部缓冲区的指针,该缓冲区立即超出范围并在函数返回后立即被释放。

      【讨论】:

      • 更准确地说,分配的字符串(临时)不是在函数本身返回时被销毁,而是在调用 func3() 的表达式结束时被销毁。这不是一个微妙之处。这是 C++ 标准所保证的特性。
      猜你喜欢
      • 1970-01-01
      • 2013-03-26
      • 2015-09-15
      • 2016-03-16
      • 1970-01-01
      • 2010-12-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      相关资源
      最近更新 更多