Proszę wziąć pod uwagę ten kod. Widziałem ten typ kodu kilka razy. words
jest wektorem lokalnym. Jak można go zwrócić z funkcji?
Czy 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;
}
std::vector<std::string>&
Odpowiedzi:
Dopóki nie zostanie zwrócone żadne odniesienie, można to zrobić w porządku.
words
zostanie przeniesiony do zmiennej otrzymującej wynik.Zmienna lokalna wyjdzie poza zakres. po przeniesieniu (lub skopiowaniu).
źródło
Przed C ++ 11:
Funkcja nie zwróci zmiennej lokalnej, ale raczej jej kopię. Twój kompilator może jednak przeprowadzić optymalizację, w której nie jest wykonywana żadna czynność kopiowania.
Zobacz to pytanie i odpowiedź, aby uzyskać więcej informacji.
C ++ 11:
Funkcja przesunie wartość. Więcej szczegółów znajdziesz w tej odpowiedzi .
źródło
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, ponieważ tablica zwraca (jeśli zapiszesz ją w prosta forma) zwracają wskaźnik do rzeczywistej tablicy na stosie, która jest następnie natychmiast usuwana po powrocie funkcji.
Ale w tym przypadku działa, ponieważ
std::vector
jest klasą, a klasy, podobnie jak struktury, mogą (i będą) kopiowane do kontekstu wywołującego. [Właściwie większość kompilatorów optymalizuje ten konkretny typ kopii za pomocą czegoś, co nazywa się „Optymalizacją wartości zwracanej”, wprowadzonej specjalnie w celu uniknięcia kopiowania dużych obiektów zwracanych z funkcji, ale jest to optymalizacja, az punktu widzenia programistów będzie to zachowują 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 powracającej funkcji, wszystko jest w porządku.
źródło
Aby dobrze zrozumieć zachowanie, możesz uruchomić ten kod:
Wynik jest następujący:
Zauważ, że ten przykład został dostarczony w kontekście C ++ 03, można go ulepszyć dla C ++> = 11
źródło
Nie wyrażam zgody i nie polecam zwrotu
vector
:To jest dużo szybsze:
Testowałem w programie Visual Studio 2017 z następującymi wynikami w trybie wydania:
8.01 MOP-ów przez odniesienie
5.09 MOPs powrotny wektor
W trybie debugowania jest znacznie gorzej:
0,053 MOPS przez odniesienie
0,034 MOPs przez wektor powrotu
źródło
W rzeczywistości jest to błąd projektu. Nie powinieneś używać wartości zwracanej do niczego, co nie jest prymitywem, do niczego, co nie jest względnie trywialne.
Idealne rozwiązanie powinno zostać zaimplementowane poprzez parametr zwrotny z decyzją o referencji / wskaźniku i właściwym użyciu „const \ 'y \' ness” jako deskryptora.
Ponadto należy zdać sobie sprawę, że etykieta tablicy w C i C ++ jest w rzeczywistości wskaźnikiem, a jej subskrypcja jest w rzeczywistości symbolem przesunięcia lub dodania.
Tak więc etykieta lub ptr array_ptr === etykieta tablicy zwracająca foo [offset] tak naprawdę mówi zwracać element w miejscu wskaźnika pamięci foo + offset typu return type.
źródło