返回一个不会发生内存泄漏的c++ std::string对象

Is returning a C++ std::string object safe from memory leaks?

本文关键字:泄漏 内存 c++ std 对象 string 一个 返回      更新时间:2023-10-16

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

string somefunc( void ) {
    string returnString;
    returnString.assign( "A string" );
    return returnString;
}
void anotherfunc( void ) {
    string myString;
    myString.assign( somefunc() );
    // ...
    return;
}

我的理解是,returnString的值被分配给一个新的对象myString,然后作为解决调用somefuncc的一部分,returnString对象被销毁。在将来的某个时候,当myString超出作用域时,它也会被销毁。

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

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

string myString = somefunc();

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

std::string管理自己的内存,并且它有正确编写的复制构造函数和赋值操作符,所以这样使用字符串是安全的。

Yes by doing

   return returnString

您正在调用字符串的复制构造函数。它将returnString的*复制到临时(也称为rValue)中,该临时(rValue)在调用表达式中代替"somefunc()":

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

这又被传递给assign,并被assign用来执行对myString的复制。

所以在你的例子中,string的复制构造函数保证了深度复制,并确保没有内存泄漏。

*注意,这可能是也可能不是一个真正的深度复制,复制构造函数的行为是具体实现的。一些字符串库实现了写时复制(copy-on-write),它有一些内部簿记功能,以防止在实际需要之前进行复制。

您是完全安全的,因为您是按值返回字符串,其中字符串将被"复制",而不是通过引用。如果你要返回一个std::string &,那么你就做错了,因为你有一个悬空引用。有些编译器甚至可能执行返回值优化,这甚至不会在返回时真正复制字符串。

是的,它(至少通常)是安全的。几乎所有合理的字符串类最基本的贡献之一就是能够充当一个基本值,而普通赋值、返回等"只是工作"。

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

你想要的是给myStringsomefunc的引用(不要使用指针)。这将非常清楚:

void somefunc( string& myString ) {
  myString.assign( "A string" );
}
void anotherfunc( void ) {
  string myString;
  somefunc(myString);
  // ...
  return;
}