1

我读过这个问题“为什么 C++ 不支持返回数组的函数? ”。据说当我们试图从这个函数外部(通过返回值)访问数组时,我们遇到了一个问题,因为我们试图访问不在您正在使用的范围内的内存(函数调用的堆栈)。

当我们返回在函数内部声明的 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

4 回答 4

2

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

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

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

于 2013-04-12T02:29:20.600 回答
2

是的,在您的示例中,它将调用复制构造函数进行复制,原始副本将超出范围,但返回的副本不会并且可用于对其进行操作,例如分配给main. 由于现在编译器会进行返回值优化RVO或命名返回值优化,因此该成本已降至最低。

于 2013-04-12T02:30:42.243 回答
1

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

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

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

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

于 2013-04-12T02:44:42.237 回答
1

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

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

于 2013-04-12T02:50:50.017 回答