为什么从函数返回向量是可以的?

Pra*_*ari 106 c++ scope stl vector standard-library

请考虑此代码.我已经多次看过这种类型的代码了.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;
}
Run Code Online (Sandbox Code Playgroud)

Tim*_*yer 105

前C++ 11:

该函数不会返回局部变量,而是返回它的副本.但是,您的编译器可能会执行优化,而不会进行实际的复制操作.

有关详细信息,请参阅此问题和答案

C++ 11:

该函数将移动该值,请参阅此答案以获取更多详细信息

  • 没有C++ 10这样的东西. (27认同)
  • C++ 11独有的问题有一个单独的标签.我们中的许多人,特别是大公司的程序员仍然坚持不完全支持C++ 11的编译器.我更新了这两个标准的问题. (19认同)
  • 那么'旧'C++ (3认同)
  • 它将被移动,而不是被复制.这是有保证的. (2认同)

πάν*_*ῥεῖ 67

我们可以保证它不会死吗?

只要没有返回引用,这样做就完全没问题了.words将被移动到接收结果的变量.

局部变量将超出范围.移动(或复制)后.

  • 但对于可以容纳1000个条目的向量是否有效或有任何性能问题? (2认同)
  • 不是没有真正的问题,但我从这个角度独立寻找答案.我不知道我是否发布了我的问题,我担心他们会将此标记为重复:) (2认同)

Mat*_*son 24

我认为您指的是C(和C++)中的问题,即不允许从函数返回数组(或者至少不能按预期工作) - 这是因为数组返回将(如果您在简单形式)返回指向堆栈上实际数组的指针,然后在函数返回时立即删除.

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

只要你没有返回一个指针或对返回函数内的东西的引用,你就可以了.


Cad*_*hon 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 Code Online (Sandbox Code Playgroud)

输出如下:

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()
Run Code Online (Sandbox Code Playgroud)