C++ 函数返回一个向量/字符串,但不是一个数组

Posted

技术标签:

【中文标题】C++ 函数返回一个向量/字符串,但不是一个数组【英文标题】:C++ function return a vector / string but not an array 【发布时间】:2013-04-12 02:25:16 【问题描述】:

我已阅读此问题“Why doesn't C++ support functions returning arrays?”。据说当我们试图从这个函数外部(通过返回值)访问数组时,我们遇到了一个问题,因为我们试图访问不在您正在使用的范围内的内存(函数调用的堆栈)。

当我们返回一个在函数内部声明的 std::string 或 std::vector 或者 C++ 复制字符串或向量并将副本返回给调用者以便字符串或矢量不会超出范围。

vector<int> foo(const vector<int> a)

  vector<int> b = a;
  return b;
 

int main()

   vector<int> a;
   vector<int> c = foo(a);

【问题讨论】:

vector&lt;int&gt; b from foo(...) 将被复制到 c。执行后,ac 将是同一个对象的副本。 咳咳... int 主要... 谢谢,已编辑为 int main 【参考方案1】:

它正在复制 std::vector 对象。 std::vector 用于存储其数据的内存在堆上分配(并且也被复制)。

(一些编译器优化意味着副本并不总是在幕后发生;例如,在您的示例代码中,我认为大多数编译器将从a 复制到b,在foo() 内,但b将成为main() 中的c 而不会被再次复制。)

延伸阅读:http://en.wikipedia.org/wiki/Copy_elision 和 http://en.wikipedia.org/wiki/Return_value_optimization(感谢 millsj 的建议) Scott Meyers 撰写的更有效的 C++ 的第 20 条也涵盖了这一点。

【讨论】:

【参考方案2】:

是的,在你的例子中,它会调用复制构造函数进行复制,原始副本将超出范围,但返回的副本不会并且可以用于对其进行操作,例如分配给其他main 中的对象。由于现在编译器会做返回值优化RVO 或命名返回值优化,所以这个成本被最小化了。

【讨论】:

【参考方案3】:

添加到其他人已经提到的内容。

优化开启时: NRVO 或 RVO 确保返回值是就地计算而不是复制回调用者。

当所有优化都关闭时:返回一个向量或一个字符串就像返回一个对象(具体来说,一个容器类型的对象,其大小对于编译器来说是已知的)。 由于编译器知道返回对象的大小,因此它有足够的信息来为按值复制分配所需的堆栈空间。

如果您尝试返回一个数组(任何类型),编译器如何知道要在堆栈上分配多少大小? 是否应该强制 C++ 返回一个固定大小的数组?

【讨论】:

我了解到 vector v1 将在堆栈上分配 v1(标题信息)并将 v1 的数据元素存储在堆上。在这里,返回对象(向量 b)在被复制到 c 之前是否会被复制到堆栈或堆中。上一个答案暗示向量在被复制之前存储在堆中。 向量内部对象将在堆上(对于基于堆栈的向量,只有元信息或标题信息进入堆栈)。要在堆栈上分配编译器应该知道要创建多少个对象。此信息不可用,因此唯一剩下的选择是从堆中为包含的对象分配内存。 看看***.com/questions/15701597/…【参考方案4】:

返回一个对象将触发一个复制构造函数来拥有临时向量对象,该对象将作为复制构造函数分配给 b。源对象超出范围后将被销毁。

大多数现代编译器都有一种称为“返回值优化”(简称 RVO)的优化。 C++11 RValue 引用允许保证 ROV 的向量实现。

【讨论】:

以上是关于C++ 函数返回一个向量/字符串,但不是一个数组的主要内容,如果未能解决你的问题,请参考以下文章

传递给函数时找不到c ++向量?

c++ vector 为啥叫向量

C++ 从函数调用的多次返回中构建字符串向量的最佳方法

如何从函数中返回字符串

C++ 如何制作二维向量函数?

char数组的C++向量