返回一个 C++ std::string 对象是不是可以避免内存泄漏?

Posted

技术标签:

【中文标题】返回一个 C++ std::string 对象是不是可以避免内存泄漏?【英文标题】:Is returning a C++ std::string object safe from memory leaks?返回一个 C++ std::string 对象是否可以避免内存泄漏? 【发布时间】:2011-08-22 15:52:06 【问题描述】:

我对 C++ 的字符串相当陌生,所以下面的模式可能有点难看。在开始使用更大的系统进行集成测试之前,我正在查看我编写的一些代码。我想知道的是它是否安全,或者它是否容易泄漏内存?

string somefunc( void ) 
    string returnString;
    returnString.assign( "A string" );
    return returnString;


void anotherfunc( void ) 
    string myString;
    myString.assign( somefunc() );
    // ...
    return;

我的理解是returnString 的值被分配给一个新对象myString,然后returnString 对象被销毁作为解析对somefunc 的调用的一部分。在未来的某个时刻,当 myString 超出范围时,它也会被销毁。

我通常会将指向 myString 的指针传递给 somefunc() 并直接分配给 myString 的值,但我正在努力使我的代码更清晰一点(并且依赖于副作用函数样式 less )。

【问题讨论】:

在第一个函数中,您可能只需要执行 "return string("A string");"并得到相同的结果。 @luiscubal 这是一个用于说明问题的简化示例。 @luiscubal 甚至 return "A string"; 都可以,因为 std::string 可以用 c 字符串构造。 @Ugo 没错,我忘了。 【参考方案1】:

是的,以这种方式(按值)返回 string 是安全的,尽管我更喜欢以这种方式分配它:

string myString = somefunc();

这更容易阅读,也更有效(保存空字符串的构造,然后将被下一次调用assign覆盖)。

std::string 管理自己的内存,并且已经正确编写了复制构造函数和赋值运算符,因此这样使用字符串是安全的。

【讨论】:

【参考方案2】:

是的

   return returnString

您正在调用字符串的copy constructor。它将returnString的副本*复制到临时(又名rValue)中,以代替调用表达式中的“somefunc()”:

   myString.assign( somefunc() /*somefunc()'s return becomes temporary*/);

这又被传递给assign并被assign用于执行复制到myString。

因此,在您的情况下,字符串的复制构造函数保证了深层复制并确保没有内存泄漏。

* 请注意,这可能是也可能不是真正的深层复制,复制构造函数的行为是特定于实现的。一些字符串库实现了写时复制,它有一些内部簿记以防止在实际需要之前复制。

【讨论】:

实际上,是否执行深拷贝完全取决于您使用的特定标准库实现。 GCC 使用的是 COW,所以复制构造函数只是意味着增加一个计数器。【参考方案3】:

您是完全安全的,因为您按值返回字符串,字符串将被“复制”,而不是通过引用。如果你要返回一个std::string &,那么你做错了,因为你会有一个悬空的参考。甚至一些编译器可能会执行返回值优化,这甚至不会在返回时真正复制字符串。请参阅this post 了解更多信息。

【讨论】:

【参考方案4】:

是的,它(至少通常)是安全的。几乎所有合理的字符串类的最基本贡献之一是能够像正常赋值、返回等的基本值一样“正常工作”。

【讨论】:

【参考方案5】:

正如您所说,在somefunc 内部创建了一个字符串returnString,并在函数返回时返回一个副本。这是绝对安全的。

您想要的是将myString 引用到somefunc(不要使用指针)。这将非常清楚:

void somefunc( string& myString ) 
  myString.assign( "A string" );


void anotherfunc( void ) 
  string myString;
  somefunc(myString);
  // ...
  return;

【讨论】:

这绕过了编译器通常执行的返回值优化,所以它不是一个改进。 What you want is to... 你为什么这么说?我认为您的代码与他所做的相比几乎没有优势。

以上是关于返回一个 C++ std::string 对象是不是可以避免内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

C++:指向 std::string 转换的 char 指针是不是复制内容?

从 C++ 函数 Cython 返回包含 PyObject 的复杂对象

当函数返回它时,C++ 向量实例是可操作的

C++ std::string::size()函数(返回字符串的长度,以字节为单位)(与std::string::length()函数相同)

C语言中有string吗?

GCC 如何连接多个 C++ std::string 变量?