C++ 为什么可以从函数返回“向量”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22655059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is it OK to return a 'vector' from a function?
提问by Pranit Kothari
Please consider this code. I have seen this type of code several times. words
is a local vector. How is it possible to return it from a function?
请考虑此代码。我已经多次看到这种类型的代码。words
是局部向量。如何从函数中返回它?
Can we guarantee it will not die?
我们能保证它不会死吗?
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;
}
采纳答案by π?ντα ?ε?
Can we guarantee it will not die?
我们能保证它不会死吗?
As long there is no reference returned, it's perfectly fine to do so. words
will be moved to the variable receiving the result.
只要没有返回引用,这样做就完全没问题。words
将被移动到接收结果的变量。
The local variable will go out of scope. after it was moved (or copied).
局部变量将超出范围。在移动(或复制)之后。
回答by Tim Meyer
Pre C++11:
C++11 之前:
The function will not return the local variable, but rather a copy of it. Your compiler might however perform an optimization where no actual copy action is made.
该函数不会返回局部变量,而是返回它的副本。但是,您的编译器可能会执行优化,而不会进行实际的复制操作。
See this question & answerfor further details.
有关更多详细信息,请参阅此问答。
C++11:
C++11:
The function will move the value. See this answerfor further details.
该函数将移动该值。有关更多详细信息,请参阅此答案。
回答by Mats Petersson
I think you are referring to the problem in C (and C++) that returning an array from a function isn't allowed (or at least won't work as expected) - this is because the array return will (if you write it in the simple form) return a pointer to the actual array on the stack, which is then promptly removed when the function returns.
我认为您指的是 C(和 C++)中的问题,即不允许从函数返回数组(或至少不会按预期工作)-这是因为数组返回将(如果您将其写入简单形式)返回一个指向堆栈上实际数组的指针,然后在函数返回时立即删除该指针。
But in this case, it works, because the std::vector
is a class, and classes, like structs, can (and will) be copied to the callers context. [Actually, most compilers will optimise out this particular type of copy using something called "Return Value Optimisation", specifically introduced to avoid copying large objects when they are returned from a function, but that's an optimisation, and from a programmers perspective, it will behave as if the assignment constructor was called for the object]
但在这种情况下,它起作用了,因为它std::vector
是一个类,并且类,如结构,可以(并且将)被复制到调用者上下文中。[实际上,大多数编译器会使用称为“返回值优化”的东西来优化这种特定类型的副本,特别是为了避免从函数返回时复制大对象,但这是一种优化,从程序员的角度来看,它会表现得好像为对象调用了赋值构造函数]
As long as you don't return a pointer or a reference to something that is within the function returning, you are fine.
只要您不返回指针或对返回函数内某些内容的引用,就可以了。
回答by Caduchon
To well understand the behaviour, you can run this code:
要很好地理解行为,您可以运行以下代码:
#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;
}
The output is the following:
输出如下:
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()
回答by mathengineer
I do not agree and do not recommendto return a vector
:
我不同意也不建议返回一个vector
:
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;
}
This is much faster:
这要快得多:
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];
}
I tested on Visual Studio 2017 with the following results in release mode:
我在 Visual Studio 2017 上进行了测试,在发布模式下的结果如下:
8.01 MOPs by reference
5.09 MOPs returning vector
8.01 MOPs 参考
5.09 MOPs 返回向量
In debug mode, things are much worse:
在调试模式下,情况更糟:
0.053 MOPS by reference
0.034 MOPs by return vector
0.053 MOPS 参考
0.034 MOP返回向量
回答by Newbstarr
This is actually a failure of design. You shouldn't be using a return value for anything not a primitive for anything that is not relatively trivial.
这实际上是设计的失败。你不应该为任何不是相对微不足道的东西使用返回值。
The ideal solution should be implemented through a return parameter with a decision on reference/pointer and the proper use of a "const\'y\'ness" as a descriptor.
理想的解决方案应该通过一个返回参数来实现,该参数决定了引用/指针,并正确使用“const\'y\'ness”作为描述符。
On top of this, you should realise that the label on an array in C and C++ is effectively a pointer and its subscription are effectively an offset or an addition symbol.
最重要的是,您应该意识到 C 和 C++ 中数组上的标签实际上是一个指针,其订阅实际上是一个偏移量或加法符号。
So the label or ptr array_ptr === array label thus returning foo[offset] is really saying return element at memory pointer location foo + offset of type return type.
所以标签或 ptr array_ptr === 数组标签因此返回 foo[offset] 实际上是在说返回元素在内存指针位置 foo + 类型返回类型的偏移量。