【发布时间】:2015-01-29 18:58:21
【问题描述】:
假设我在 C++ 中有一个函数 A(),它调用另一个函数 B()。 B() 打开一个文件并读取一个较长的字符串,然后将该字符串返回给 A()。比 A() 使用此字符串作为 C() 的输入参数。 C() 期待一个对字符串的引用。
为此,我看到了两种解决方案:
B() 获取对字符串的引用作为 输入参数(称为 str)。 B() 编辑 str ,因此 A() 获取字符串。释放分配的内存是 A() 的职责。当 A() 使用字符串完成时,它会将内存返回给系统。这一点我很清楚。
B() 返回一个字符串。我对这个选项感到困惑。那么谁释放分配的内存呢? B() 创建一个本地字符串,因此不能返回其地址。 B() 必须按值返回参数。据我所知,由于返回值优化,没有创建字符串的实际副本。在后台,参数仍然是通过引用传递的。当我写类似这样的伪代码时:
A() { C(B(filename)) }
与分配的内存相比会发生什么? B() 获取文件名,打开文件,为它从文件中读取的字符串分配一个内存块,然后返回这个字符串。这是 B() 生命范围的终结。 A() 没有定义一个变量来处理这个字符串。谁把这个内存块还给我? 我可以依靠 RVO 吗?性能按值返回是否可以?每个编译器都有吗?
【问题讨论】:
-
按值返回:请阅读返回值优化(复制省略)和右值引用。
-
@DieterLücking RVO 在问题中被反复提及,所以显然 OP 知道这一点。
-
你不用担心编译器是否支持RVO。从 C++11 开始,移动语义(由右值引用提供)保证返回字符串(或任何具有移动构造函数的对象)非常有效。
-
@Ferrucio Tnahk 你,RVO 部分现在很清楚。释放内存怎么样?在 Java 中,我会依赖垃圾收集器并说如果没有人使用这些数据,垃圾收集器会处理它。但是在 C++ 中会发生什么?
-
@lulijeta:在 C++ 中,主要的范例是 RAII。
std::string紧随其后,因此当使用它的std::string对象超出范围(或以其他方式销毁)时,内存将被释放。
标签: c++ string memory-management return-value return-value-optimization