Как вернуть vector из функции c
Перейти к содержимому

Как вернуть vector из функции c

  • автор:

Как вернуть vector из функции: по значению или по ссылке?

Есть функция, создающая каким-то определенным образом экземпляр vector . Вопрос: как вернуть этот экземпляр вызывающему?

Правильное с точки зрения логики и стройности программы решение выглядит так:

Тут экземпляр вектора возвращается по значению, что означает потенциальное глубокое копирование локального объекта в контекст вызывающей функции. Сразу возникает сомнение: а что, если вектор огромен — его ж надо будет побайтно перекладывать из одного места в другое? Гораздо “разумнее” было бы написать:

Тут вектор передается по указателю, и стопроцентно ненужного полного копирования не будет. Но такой код выглядит откровенно плохо.

Сравним скорости работы на векторе длиной 100MB. Например, на компиляторе:

Теперь по указателю:

Время в обоих случаях одинаково. Получается, что стоит выбрать первый, “красивый” вариант.

Объяснений тут два. Первый, и возможно самый важный — это RVO, Return value optimization. Это когда компилятор догадывается, что создаваемый локальный экземпляр вектора предназначен для возврата из функции, и сразу создает его в контексте вызывающего кода, чтобы потом не копировать туда. Фактически компилятор реализует передачу по ссылке, но неявно, не портя красоту исходного кода. Данный трюк будет работать для любого класса, не обязательно класса из STL.

Но оптимизация — это негарантированная вещь. Но тут есть еще одно подспорье. Стандартные контейнеры STL реализованы так, что при даже при глубоком копировании фактически копируется только небольшая управляющая структура, а сами данные, размещенные в куче, просто перебрасываются указателем, без их фактического перемещения. Тут, конечно, будет небольшое дополнительное копирование, но оно минимально, и возможно на него стоит пойти ради сохранения красивого кода.

Ну а в контексте C++11, где есть семантика перемещения, вообще не будет лишних копирований, если класс “правильно” реализован (что верно для классов из STL).

Мораль: используйте по возможности контейнеры из STL и оставьте оптимизацию компилятору. Иногда, конечно, компилятор ошибается, но таких случаев гораздо меньше, чем наоборот.

Возврат вектора из функции

Как вывести вектор из функции через адреса или указатели? Можно и внутри вектор создать, его главное вывести.

Возврат 2 значений из функции с одним вызовом этой же функции
Вообщем где то в какой то игре была хукнута одна функция int function(int arg1,int arg2,int.

Вычисление вектора значений функции для нового вектора аргумента
Здравствуйте господа. При вычислении значений функции для нового вектора вместо значений в "Р".

Возврат функции
Не могу сообразить как в этом коде Страуструпа указать возврат функции return, чтобы выполнились.

Сообщение от Croessmah

вы что-то внутри своей билд функции напутали скорее всего. вот почти копия того, что вы пытаетесь сделать:
http://cpp.sh/4iyq

Сообщение от AleksandrMild
Сообщение от Kerry_Jr

Спасибо за ответ, в этом месте помогло. Я не знал о таком символе как ‘->’.

Ниже выскочила другая ошибка при присвоении элементу вектора числа.

Сообщение от AleksandrMild

Возврат функции
Всем доброго времени суток! Пишу трейд-бота для стима( принимает вещи и отдает их в автоматическом.

возврат функции
Здравствуйте. Мне нужно, чтобы при выборе функции с помощью radiobutton, она была именно как.

Возврат массива из функции
Есть задача: используя функции, вычислить количество элементов заранее введённых массивов, которые.

Возврат значения из функции
Добрый вечер. Не могу вернуть значение из функции после connect(сигнала) или не так делаю. И еще.

Returning vector from function in C++

Return vector in C++

It is a preferred method to return vector from function in C++. It can reduce the execution time and space because in this method, an object is not copied for returning a vector. It only points the pointer to the vector which will be returned.

Code:

Further reading:

Vector in C++
Return array from function in C++

Return by Reference

This method is better for returning large classes and structures. We will not return the reference of the local variable which is declared in the function because that can lead to dangling reference. In this method, we pass the vector by reference(& myFunction) and we will return as reference only.

Code:

Conclusion

In this article we discussed two efficient methods to return vector in C++. We can use return by value for smaller classes or structures. Return by reference method is only useful in the case of large structures and classes.

That’s all about how to return vector from function in C++.
Happy Learning!!

Was this post helpful?

Share this

Input Validation in C++

Convert int to Char Array in C++

Related Posts

Author

Related Posts

Pass 2D Array to Function in C++

Table of ContentsWays to Pass a 2D Array to function in C++Pass a 2D Array to a Function by Passing Its PointerPass an Array to the Function by Decaying the Pointer to the ArrayPass a 2D Array to a Function in C++ Without Size by Passing Its ReferenceConclusion Two-dimensional arrays have rows and columns, storing […]

Count Decimal Places in C++

Table of ContentsAccuracy V/S Precision in Counting Decimal Places in C++ ProgramsHow to Count Decimal Places in C++Example 1: Use String Functions to Find Precise Number of Decimal PlacesExample 2: Count Decimal Places Accurately for a NumberExample 3: Create a Program that divides two numbers and returns their decimal placesMethod – decimal_placesMethod – print_resultsExample 4: […]

Check if String Is Empty in C++

Table of ContentsWays to Check if String Is Empty in C++Using Empty() methodUsing the Equality OperatorUsing length() methodUsing size() methodConclusion A String is a combination of characters that can store both alphabets and numbers together. In C, there was no concept of string as a datatype so character arrays were used. In C++, this drawback […]

Get Filename from Path in C++

Table of ContentsGet Filename From Path in C++Using find_last_of and substr methodsMethod clear_slash():Method extension_removal():main_function:Using TemplatesUsing filesysystem library [ C++ 17 ]Conclusion This article explains the various ways to get filename from path using C++ programs. The examples will also describe ways to remove extensions as well if such needs arise. Get Filename From Path in […]

Escape Percent Sign in printf Method in C++

In this post, we will see how to escape percent sign in printf Method in C++. Escape percent sign in Printf Method in C++ printf() method uses percent sign(%) as prefix of format specifier. For example: To use number in prinf() method, we use %d, but what if you actually want to use percent sign […]

Remove Last Element from Vector in C++

Table of ContentsWays to Remove Last Element from Vector in C++Using the vector::pop_back() function to remove last element from vector in C++Using the vector::resize() Function to Remove Last Element from Vector in C++Using the vector::rrase() Function to Remove Last Element from Vector in C++Conclusion Learn about how to remove last element from Vector in C++. […]

Возврат вектора из функции

Как правильно возвращать вектор из функции — возвращать сам вектор, указатель на него или итератор? «Правильность» интересует с точки зрения оптимального использования ресурсов и хорошего стиля программирования.

DarkGenius's user avatar

Давайте-ка я суммирую дискуссию в комментариях здесь.

Классическим методом является передача пустого вектора по ссылке в функцию, с тем чтобы функция его заполнила.

Затем, если вы уверены, что время жизни вектора, который вы передаёте, достаточно велико (например, вектор является полем класса), то вы можете возвращать ссылку на него. Внимание! При этом вы вводите потенциально опасную зависимость: если сам объект умрёт, ссылка на вектор тоже перестанет быт валидной! Сам объект не может знать, как его используют, и не является ли он, например, временным.

Затем, вы вполне можете вернуть вектор по значению, особенно если вы конструируете его на стеке в самой функции (и значит, не можете вернуть ссылку на него). Это кажется излишним копированием, но на самом деле оптимизатор часто может убрать ненужное копирование используя RVO/NRVO. (Вот ссылкf про это: NRVO in Visual C++ 2005). Тем не менее, иногда эта техника может всё же ведёт к копированию (например, потому, что оптимизатор не волшебник) и показывает плохие результаты.

И ещё: я бы не советовал возвращать итератор. Итераторы в C++ — ещё более хрупкая вещь, чем ссылки: любой чих в сторону вектора может его инвалидировать.

Возврат итератора требует фактического хранения вектора после завершения работы. Т.е. либо вектор должен быть статичным (объявлен с ключевым словом static ), либо как член класса, а возвращать его будет метод, либо получен на вход функции ещё откуда-либо.

С одним лишь итератором многого не сделать: неизвестно, например, сколько ещё элементов после текущего итератора можно прочитать (для этого придётся возвращать пару итераторов, итератор и длину остатка или что-то подобное), нельзя вставить новый элемент или удалить существующий. С другой стороны, итератор концептуально представляет собою позицию в контейнере (плюс вариант отсутствия когда итератор указывает на end ).

Итого: если вам нужна именно семантика указателя на позицию в контейнере, итератор вам подойдёт. В остальных случаях ничего хорошего не выйдет.

Возврат указателя можно разделить на 2 случая: с передачей владения и без (т.е. определить, кто занимается удалением вектора).

Если владение не передаётся, остаются всё те же требования к времени жизни рассматриваемого вектора, как и в предыдущем пункте. В таком случае можно также вернуть ссылку на вектор — подходы будут эквивалентны.

Если нужно передать владение вектором вызывающему контексту, следует изначально создавать его на куче (с помощью оператора new ). С точки зрения идиоматичного C++ следует использовать умные указатели shared_ptr , unique_ptr или их аналоги из библиотек вроде boost или Qt .

Следует заметить, что в C++11 такой подход довольно бессмыслен, поскольку там существует семантика перемещения (об этом позже). С другой стороны, shared_ptr доступен и в C++03 с TR1. Правда, он может быть не совсем эквивалентен своему собрату из 11 стандарта.

Возврат по значению может вылиться в дорогостоящее копирование, однако:

В C++11 (который на текущий момент с нами уже 4 года, между прочим) существует семантика перемещения, которая позволит вернуть вектор по значению без копирования.

Даже для более старых стандартов многие компиляторы реализуют оптимизации Return Value Optimization и Named Return Value Optimization (подробнее о этих товарищах можно почитать у Алёны C++). Несмотря на то, что большинство компиляторов поддерживают эти оптимизации, могут существовать экзотические / старые компиляторы, не проводящие их.

Следует отметить, что эта оптимизация не всегда срабатывает. Один из таких случаев — когда возвращаемый результат зависит от пути исполнения, например

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *