请考虑此代码。我已经多次看过这种类型的代码了。 words
是本地向量。如何从函数中返回它?我们可以保证它不会死吗?
std::vector<std::string> read_file(const std::string& path)
{
std::ifstream file("E:\\names.txt");
if (!file.is_open())
{
std::cerr << "Unable to open file" << "\n";
std::exit(-1);
}
std::vector<string> words;//this vector will be returned
std::string token;
while (std::getline(file, token, ','))
{
words.push_back(token);
}
return words;
}
答案 0 :(得分:101)
该函数不会返回局部变量,而是返回它的副本。但是,您的编译器可能会在没有进行实际复制操作的情况下执行优化。
有关详细信息,请参阅this question & answer
该函数将移动该值,有关详细信息,请参阅this answer
答案 1 :(得分:66)
我们可以保证它不会死吗?
只要没有返回引用,这样做就完全没问题了。 words
将移动到接收结果的变量。
局部变量将超出范围。移动(或复制)之后。
答案 2 :(得分:24)
我认为你指的是C(和C ++)中的问题,即从一个函数返回一个数组是不允许的(或者至少不会按预期工作) - 这是因为数组返回将(如果您以简单形式编写)返回指向堆栈上实际数组的指针,然后在函数返回时立即删除。
但是在这种情况下,它可以工作,因为std::vector
是一个类,并且类(如结构)可以(并且将会)复制到调用者上下文。 [实际上,大多数编译器会使用名为&#34;返回值优化&#34;的东西来优化这种特定类型的副本,专门用于避免在从函数返回时复制大对象,但这是一个优化从程序员的角度来看,它的行为就像为对象调用赋值构造函数一样
只要你没有返回指针或对函数返回内容的引用,你就可以了。
答案 3 :(得分:12)
为了更好地理解行为,您可以运行以下代码:
#include <iostream>
class MyClass
{
public:
MyClass() { std::cout << "run constructor MyClass::MyClass()" << std::endl; }
~MyClass() { std::cout << "run destructor MyClass::~MyClass()" << std::endl; }
MyClass(const MyClass& x) { std::cout << "run copy constructor MyClass::MyClass(const MyClass&)" << std::endl; }
MyClass& operator = (const MyClass& x) { std::cout << "run assignation MyClass::operator=(const MyClass&)" << std::endl; }
};
MyClass my_function()
{
std::cout << "run my_function()" << std::endl;
MyClass a;
std::cout << "my_function is going to return a..." << std::endl;
return a;
}
int main(int argc, char** argv)
{
MyClass b = my_function();
MyClass c;
c = my_function();
return 0;
}
输出如下:
run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run constructor MyClass::MyClass()
run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run assignation MyClass::operator=(const MyClass&)
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()
答案 4 :(得分:-2)
我不同意也不建议返回向量:
vector <double> vectorial(vector <double> a, vector <double> b)
{
vector <double> c{ a[1] * b[2] - b[1] * a[2], -a[0] * b[2] + b[0] * a[2], a[0] * b[1] - b[0] * a[1] };
return c;
}
这快得多:
void vectorial(vector <double> a, vector <double> b, vector <double> &c)
{
c[0] = a[1] * b[2] - b[1] * a[2]; c[1] = -a[0] * b[2] + b[0] * a[2]; c[2] = a[0] * b[1] - b[0] * a[1];
}
我在VS2017上进行了测试,并在发布模式下获得了以下结果:
8.01 MOP(参考) 5.09 MOP返回向量
在调试模式下,情况更糟:
通过参考0.053 MOPS 返回向量为0.034 MOPs
答案 5 :(得分:-8)
这实际上是设计的失败,对于任何不是相对微不足道的事情,你不应该为任何不是原语的东西使用返回值。理想的解决方案应该通过返回参数来实现,该参数决定了参考/ ptr以及正确使用&#34; const \&#39; \ n&#39; ness&#34;作为描述符。
除此之外,你应该意识到C和C ++中数组上的标签实际上是一个指针,它的订阅实际上是一个偏移量或一个附加符号。
因此返回foo [offset]的标签或ptr array_ptr ===数组标签实际上是在内存ptr位置foo +返回类型返回类型的返回元素。