这是我的困惑。我认为s1
和s2
是类型string
的函数本地对象实例,我们不应该将函数本地范围对象返回到外部。但似乎下面的代码工作,想知道为什么?
vector<string> testString(){
vector<string> result;
string s1 = "123";
string s2 = "456";
result.push_back(s1);
result.push_back(s2);
return result;
}
void testStringWrapper(){
vector<string> result = testString();
for (int i=0; i<result.size(); i++) {
cout << result[i] << endl;
}
}
答案 0 :(得分:4)
通过引用或指针返回任何内容,按值返回 - 这是可以接受的。根据需要执行复制/移动。
vector<string> testString(){
// Declares a vector that will be returned:
vector<string> result;
// Creates two local strings:
string s1 = "123";
string s2 = "456";
// *Copies* the local strings into the vector *by value*:
result.push_back(s1);
result.push_back(s2);
// Returns the vector *by value*. A copy might be made, but NVRO will elide it.
return result;
}
vector<string>
包含函数本地的字符串副本。
通过将字符串移动到向量中可以提高效率,而#34; pilfers&#34;来自源字符串对象的数据指针,使其处于未指定但有效的状态:
// Instead of:
// result.push_back(s1);
// result.push_back(s2);
// Move the strings:
result.emplace_back(std::move(s1));
result.emplace_back(std::move(s2));
然后没有复制,s1
和s2
不再包含各自的值 - 向量窃取了内容。
答案 1 :(得分:1)
您正在返回值,因此他们会被复制或转移到呼叫网站。那很好。
答案 2 :(得分:0)
当你这样做时:
vector<string> testString(){
vector<string> result;
...
return result;
}
在本地范围创建向量result
,但在函数超出范围之前,返回它,关键部分是函数的返回类型为vector<string>
,其中< strong>副本 result
并将其返回给函数的调用者,在您的情况下将其分配给全新的值:
vector<string> result = testString();
但请勿与result
范围和testString()
范围内testStringWrapper()
的相同名称混淆。
这两个result
向量是内存中的不同对象。这与例如vector<string> foo = testString();
相同。
我们不应该将函数局部范围对象返回到外部
在某些情况下是正确的。
当通过引用返回或指针时,这适用。在这种情况下,你会有这样的事情:
// BAD PRACTICE
vector<string>& testString(){
vector<string> result;
...
return result;
}
并且一旦函数终止,您将返回对超出范围的对象的引用。因此,当您尝试在testString()
之外访问它时,您将访问超出范围的内存。
此问题的典型解决方案是使用new
为您的对象动态分配内存,通过引用返回它,然后自己管理内存(据说,在您调用之前,内存不会被取消分配delete
就可以了。)