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

时间:2013-04-12 02:25:17

标签: c++ function vector

我已阅读此问题“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);
}

4 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

添加其他人已提及的内容。

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

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

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

答案 3 :(得分:1)

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

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