简体   繁体   English

为什么可以从函数返回“向量”?

[英]Why is it OK to return a 'vector' from a function?

Please consider this code.请考虑此代码。 I have seen this type of code several times.我已经多次看到这种类型的代码。 words is a local vector. words是一个局部向量。 How is it possible to return it from a function?如何从函数中返回它?

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;
}

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 & answer for further details.有关更多详细信息,请参阅此问答

C++11: C++11:

The function will move the value.该函数将移动该值。 See this answer for further details.有关更多详细信息,请参阅此答案

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).在移动(或复制)之后。

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.但在这种情况下,它有效,因为std::vector是一个类,并且类,如结构体,可以(并且将)被复制到调用者上下文中。 [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] [实际上,大多数编译器会使用称为“返回值优化”的东西来优化这种特定类型的副本,特别是为了避免从函数返回时复制大对象,但这是一种优化,从程序员的角度来看,它会表现得好像为对象调用了赋值构造函数]

As long as you don't return a pointer or a reference to something that is within the function returning, you are fine.只要您不返回指针或对返回函数内某些内容的引用,就可以了。

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()

Note that this example was provided in C++03 context, it could be improved for C++ >= 11请注意,此示例是在 C++03 上下文中提供的,它可以针对 C++ >= 11 进行改进

I do not agree and do not recommend to 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 8.01 MOPs 参考
5.09 MOPs returning vector 5.09 MOPs 返回向量

In debug mode, things are much worse:在调试模式下,情况更糟:

0.053 MOPS by reference 0.053 MOPS 参考
0.034 MOPs by return vector 0.034 MOPs 返回向量

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 + 类型返回类型的偏移量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM