Dlaczego warto zwracać wektor z funkcji?

Proszę wziąć pod uwagę ten kod. Widziałem ten typ kodu kilka razy. words jest wektorem lokalnym. Jak jest możliwe zwrócenie go z funkcji? Możemy zagwarantować, że nie umrze?

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

5 answers

Czy możemy zagwarantować, że nie umrze?

Tak długo, jak nie ma odniesienia zwrócone, to jest całkowicie w porządku, aby to zrobić. words zostanie przeniesiony do zmiennej otrzymującej wynik.

Zmienna lokalna wyjdzie poza zakres. po jego przeniesieniu (lub skopiowaniu).

 64
Author: πάντα ῥεῖ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 08:22:40

Pre C++11:

Funkcja nie zwróci zmiennej lokalnej, lecz jej kopię. Kompilator może jednak przeprowadzić optymalizację, w której nie zostanie wykonana żadna rzeczywista akcja kopiowania.

Zobacz to pytanie i ODPOWIEDŹ aby uzyskać więcej szczegółów

C++11:

Funkcja przeniesie wartość, zobacz ta ODPOWIEDŹ aby uzyskać więcej informacji

 92
Author: Tim Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:26

Myślę, że odnosisz się do problemu w C (i c++), że zwracanie tablicy z funkcji jest niedozwolone (lub przynajmniej nie będzie działać zgodnie z oczekiwaniami) - dzieje się tak dlatego, że zwrócenie tablicy (jeśli napiszesz ją w prostej formie) zwróci wskaźnik do rzeczywistej tablicy na stosie, która jest natychmiast usuwana po powrocie funkcji.

Ale w tym przypadku to działa, ponieważ std::vector jest klasą, A klasy, podobnie jak struktury, mogą (i będą) być kopiowane do kontekstu wywołującego. [Właściwie, większość kompilatorów optymalizuje ten konkretny typ kopii za pomocą czegoś o nazwie "Return Value Optimization", specjalnie wprowadzonego, aby uniknąć kopiowania dużych obiektów, gdy są one zwracane z funkcji, ale jest to optymalizacja, a z punktu widzenia programistów, będzie to zachowywać się tak, jakby konstruktor przypisania został wywołany dla obiektu]

Dopóki nie zwrócisz wskaźnika lub odniesienia do czegoś, co znajduje się w zwracanej funkcji, jesteś w porządku.

 23
Author: Mats Petersson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 08:28:45

Aby dobrze zrozumieć zachowanie, możesz uruchomić ten kod:

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

Wyjście jest następujące:

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()
 10
Author: Caduchon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-21 15:53:08

Jest to w rzeczywistości błąd w projektowaniu, nie powinieneś używać wartości zwrotnej do niczego, a nie prymitywnej do niczego, co nie jest stosunkowo trywialne. Idealne rozwiązanie powinno być zaimplementowane poprzez parametr powrotu z decyzją o referencji / ptr i właściwym użyciu "const\' y\ 'ness" jako deskryptora.

Poza tym powinieneś zdać sobie sprawę, że etykieta na tablicy w C i C++ jest efektywnie wskaźnikiem, a jej subskrypcja jest efektywnie przesunięciem lub dodatkiem symbol.

Tak więc etykieta lub ptr array_ptr = = = Etykieta tablicy zwracająca foo [offset] tak naprawdę mówi element return w pamięci ptr location foo + offset typu return type.

 -7
Author: Newbstarr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 01:15:07