Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/25: Рейтинг темы: голосов - 25, средняя оценка - 4.60
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

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

19.12.2016, 21:13. Показов 6111. Ответов 47
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как правильно вернуть STL контейнер из функции НЕ ПО ЗНАЧЕНИЮ?
C++
1
2
3
4
std :: map<std :: string, BTSComponent*> BTSObject :: getComponents() const
{
    return std :: move( _components );
}
Так?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.12.2016, 21:13
Ответы с готовыми решениями:

Из STL контейнера
Из STL контейнера создать 3-х мерный массив и класс который содержит этот 3-х мерный массив и вывод координат(пользователь вводит...

Выбор контейнера в STL
Здраствуйте! Нужно выбрать к этой задаче контейнер STL, который более выгодно подойдет, кроме вектора. Я думаю, что deque или map Помогите...

STL итератор на конец контейнера
Подскажите пожалуйста у меня задача сделать дерево и слизать интерфейс с STL std::map. Вопрос в следующем: когда мы обходим map итератором...

47
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
20.12.2016, 17:20  [ТС]
Студворк — интернет-сервис помощи студентам
Всем спасибо, я че-то затупил с этими перемещениями и ссылками. Да, Вы правы, есть контейнер - std :: map, как член класса. Мне нужно его вернуть из функции, но чтобы при этом не создавалась копия, так как хранит этот вектор много элементов. Я вначале не мог догнать такую элементарщину, так как вовсе запутался с &&, & и *. Я так понял, мне нужно просто вернуть этот вектор по константной ссылке, так?
C++
1
2
3
4
const std :: map<std :: string, BTSComponent*>& BTSObject :: getComponents() const
{
    return _components;
}
Если бы я возвращал, как я написал выше, с использованием std :: move(..), то потерял бы контейнер в классе, так?
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
20.12.2016, 18:07
Цитата Сообщение от Bretbas Посмотреть сообщение
Если бы я возвращал, как я написал выше, с использованием std :: move(..), то потерял бы контейнер в классе, так?
Нет. std::move() из константной функции-члена не сможет правильно преобразовать тип к не константной rvalue.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct MyClass
{
    std::vector<int> data{1,2,3,4,5};
 
    std::vector<int> remove_data()
    {
        static_assert(std::is_same<decltype(std::move(data)), std::vector<int>&&>::value, "");
        return std::move(data);
    }
 
    std::vector<int> get_data() const
    {
        static_assert(std::is_same<decltype(std::move(data)), const std::vector<int>&&>::value, "");
        return std::move(data);
    }
 
    void print() const
    {
        std::cout << "Data: ";
        for (int i : data)
            std::cout << i << " ";
    }
};
 
int main()
{
    MyClass mc;
    mc.print();
    mc.get_data(); // const
    mc.print();
    mc.remove_data();
    mc.print();
}
Bash
1
Data: 1 2 3 4 5 Data: 1 2 3 4 5 Data:
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.12.2016, 19:00
Цитата Сообщение от S_el Посмотреть сообщение
Локальные переменные и члены класса НЕ находятся в глобальном пространстве имен, поэтому можно смело их использовать(если, конечно, не нарушать (3.1), чего в коде ТС нету).
стандарт не уточняет, чем именно на самом деле может являться такое имя.
например - именем макроса, и привет коллизиям.
к тому же, глобальные имена в принципе успешно конкурируют
со всякими данными-членами классов.
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
20.12.2016, 19:25
Цитата Сообщение от hoggy Посмотреть сообщение
стандарт не уточняет, чем именно на самом деле может являться такое имя.
например - именем макроса, и привет коллизиям.
Возможно вы правы надо будет уточнить у кого-то еще на предмет того, чем может являться такое имя.
По поводу макросов...можете пояснить подробнее , желательно на примере.
Ведь так как макрос это просто текстовая подстановка выполняемая препроцессором,то разве все возможные коллизии не будут выявляться на этапе компиляции?

Цитата Сообщение от hoggy Посмотреть сообщение
к тому же, глобальные имена в принципе успешно конкурируют
со всякими данными-членами классов.
Конкурировать они могут, но у них своя область видимости, поэтому нарушения не будет.
0
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
20.12.2016, 21:28
Цитата Сообщение от S_el Посмотреть сообщение
По поводу макросов...можете пояснить подробнее , желательно на примере.
На реальном и без всяких подчеркиваний:
max из стандартных алгоритмов VS макрос max из windows.h
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
20.12.2016, 22:02
Цитата Сообщение от Croessmah Посмотреть сообщение
На реальном и без всяких подчеркиваний:
max из стандартных алгоритмов VS макрос max из windows.h
И что иллюстрирует этот пример?
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
20.12.2016, 22:41

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
max из стандартных алгоритмов VS макрос max из windows.h
Ничто так не способствует осознанию pimpl'a, как windows.h.


Хозяйкам на заметку : там определяется более 20000 макросов
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
20.12.2016, 23:35
Цитата Сообщение от S_el Посмотреть сообщение
И что иллюстрирует этот пример?
А то что раз в неделю-две создаётся тема на форуме, где начинающие используют название max, а потом не понимают суть ошибки. Подстановка макросов выполняется до процесса компиляции и, соответственно, лог ошибок из-за них просто ужасный.

Добавлено через 5 минут
Попробуйте в студии объявить функцию
C++
1
2
3
4
5
6
7
8
int max(const int *arr, const int size)
{
    int res = arr[0];
    for (int i = 1; i < size; i++)
        if (res < arr[i])
            res = arr[i];
    return res;
}
Code
1
2
3
4
5
6
Ошибка    C2059   синтаксическая ошибка: const    Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 4   
Ошибка    C2059   синтаксическая ошибка: )    Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 4   
Ошибка    C2143   синтаксическая ошибка: отсутствие ";" перед "{"  Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 5   
Ошибка    C2447   {: отсутствует заголовок функции (возможно, используется формальный список старого типа)  Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 5   
Ошибка    C2446   >: нет преобразования "int" в "int *" Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 16  
Ошибка    C2446   :: нет преобразования "int" в "int *" Проект1   D:\Workspace\VS Projects\Проект1\Проект1\Source.cpp 16
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
20.12.2016, 23:38
Цитата Сообщение от MrGluck Посмотреть сообщение
А то что раз в неделю-две создаётся тема на форуме, где начинающие используют название max, а потом не понимают суть ошибки.
Нет, это-то я понял. Я имел ввиду в контексте разговора о предполагаемом UB.
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
20.12.2016, 23:43
Цитата Сообщение от S_el Посмотреть сообщение
Нет, это-то я понял. Я имел ввиду в контексте разговора о предполагаемом UB.
Нет гарантии того, что заданные пользовательские имена не перекроются при подключении какого-нибудь стандартного заголовочного файла.
Пример того, во что это выльется - выше. Причем область видимости не спасёт.

Просто не рекомендуется это делать. Но, ИМХО, UB - слишком тяжелое обвинение.
2
20.12.2016, 23:48

Не по теме:

Цитата Сообщение от MrGluck Посмотреть сообщение
Пример того, во что это выльется - выше. Причем область видимости не спасёт.
Просто не рекомендуется это делать. Но, ИМХО, UB - слишком тяжелое обвинение.
Да, об этом следовало раньше написать для полноты изложения, не сразу понял о чем идет речь :)

0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
21.12.2016, 00:51
Цитата Сообщение от S_el Посмотреть сообщение
Конкурировать они могут, но у них своя область видимости, поэтому нарушения не будет.
cl (visual studio)
http://rextester.com/RDJ46212

gcc
http://rextester.com/KGOB62029

про макросы вообще молчу.
4
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
21.12.2016, 00:57
hoggy, спасибо за пример, утром посмотрю.
Про макросы вроде уже выяснили, что не могут быть UB т.к. вызывают ошибку до выполнения.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
21.12.2016, 01:44
Цитата Сообщение от S_el Посмотреть сообщение
Про макросы вроде уже выяснили, что не могут быть UB т.к. вызывают ошибку до выполнения.
а это уже как повезет.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.12.2016, 09:15  [ТС]
Ребят, еще один вопрос на эту тему, если я работаю в начале в дебаге, и мне нужно сделать так, чтобы я из функции вернул временный объект за счет перемещения, то так как я нахожусь в дебаге, я делаю это явно, так? Но к примеру, я знаю, что мой компилятор сможет оптимизировать код при релизе, мне нужно удалять std::move из функции?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
21.12.2016, 09:36
Цитата Сообщение от Bretbas Посмотреть сообщение
то так как я нахожусь в дебаге, я делаю это явно, так
Тут дело в том, что move в принципе не к месту написан. Не следует пытаться перемещать потроха класса пока он ещё жив
А т.к. move здесь написан с единственной целью - "оптимизировать код", то его можно смело выкинуть. Тем более, что возврат lvalue итак справляется с данной задачей.
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
21.12.2016, 11:55
Цитата Сообщение от Bretbas Посмотреть сообщение
мне нужно удалять std::move из функции?
вот так:

C++
1
2
3
4
some foo()
{
    return std::move(someObject);
}
делать вообще нельзя. такой код ломает оптимизацию.

http://rextester.com/XCO7069

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #define dFUNCTION __PRETTY_FUNCTION__
#else
    #ifdef _MSC_VER
        #define dFUNCTION __FUNCSIG__
    #else
        #define dFUNCTION __FUNCTION__
    #endif
#endif
 
#define dVIEW_FUNCTION std::cout << dFUNCTION << std::endl
 
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
 
 
#include <iostream>
#include <string>
 
 
struct some
{
    some()            { dVIEW_FUNCTION; }
    ~some()           { dVIEW_FUNCTION; }
    some(const some&) { dVIEW_FUNCTION; }
    some(some&&) noexcept      { dVIEW_FUNCTION; }
};
 
 
some move() { some s; return std::move(s); }
some nrvo() { some s; return s; }
some rvo()  { return some{}; }
 
 
int main() 
{
    std::cout<<"[move] ...\n";
    const auto test1 = move();
    
    std::cout<<"[nrvo] ...\n";
    const auto test2 = nrvo();
 
    std::cout<<"[rvo] ...\n";
    const auto test3 = rvo();
    
}
сборка в режиме:
-Wall -std=c++14 -O2 -o a.out source_file.cpp

в результате имеем:
[move] ...
some::some()
some::some(some&&)
some::~some()
[nrvo] ...
some::some()
[rvo] ...
some::some()
some::~some()
some::~some()
some::~some()
1
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
21.12.2016, 11:57
Цитата Сообщение от hoggy Посмотреть сообщение
такой код ломает оптимизацию.
Если someObject создавался в той же функции.
У ТС же возврат потрохов класса и если их нужно переместить,
то компилятор здесь сам ничего делать не будет.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
22.12.2016, 08:12  [ТС]
Ребят, а какой тип вернет auto, если функция возвращает константную ссылку?
C++
1
2
3
4
5
6
7
const std :: map<std :: string, BTSComponent*>& BTSObject :: getComponents() const
{
    return _components;
}
...
 
auto components = object -> getComponents();
Какой тип будет иметь объект components? Я конечно же расчитываю на const std :: map<std :: string, BTSComponent*>&
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.12.2016, 10:36
Цитата Сообщение от Bretbas Посмотреть сообщение
Какой тип будет иметь объект components? Я конечно же расчитываю на const std :: map<std :: string, BTSComponent*>&
Будет тип мэпа. Чтобы была ссылка, нужно писать
C++
1
auto &
а чтобы была константная ссылка, то
C++
1
auto const &
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.12.2016, 10:36

Обработка STL контейнера vector
Текст дан в виде вектора. Отсортировать элементы этого вектора и превратить на два списка так, чтобы в первом были только те элементы,...

Адаптация контейнера под STL
Учу C++, на данный момент было задание: реализовать односвязный список. Пока что реализовано не все, но возник такой вопрос: &quot;Почему...

Алгоритм выбора контейнера STL
Привет. Существует ли некая таблица по таким контейнерам с кратким описанием плюсов и минусов каждого по сравнению с другими? И в обще...

Использование контейнера string из библиотеки STL
Дан массив слов. Сформировать новое слово из символов слов массива, стоящих после последнего символа ‘*’ в слове. Сформировать предложение...

Реализация примитивного STL совместимого контейнера
Как то застрял на этом. Как правильно объявить все typedef для итератора? Нужен минимальный набросок такого контейнера.template&lt;typename...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru