返回一个 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++ std::string::size()函数(返回字符串的长度,以字节为单位)(与std::string::length()函数相同)