33 / 0 / 0
Регистрация: 07.11.2013
Сообщений: 118
|
|||||||||||||||||||||||||||||||
1 | |||||||||||||||||||||||||||||||
Куда деваются одномоментные указатели, или управление памятью в работе с std::string01.05.2014, 16:30. Показов 1516. Ответов 4
Метки нет (Все метки)
Здравствуйте!
Положим, у нас есть функция, возвращающая строку std::string, выглядящая как-то так:
Если возвращаемое значение довольно большое, то подобная операция может быть слишком затратной. Я так понимаю, что для вызовов подобных методов компилятор генерирует что-либо такое:
<Вызов метода getHome() - сохранение данных о вызове метода, если не inline> <Выполнение команды getenv -> выделение памяти под значение в функции> <Возврат из метода -> Выделение памяти под s на основании полученных данных> <Копирование из выделенной памяти в методе в s> С другой стороны, компилятор может сделать так, чтобы использовалось только память, выделенная в s. Таким образом, первый вопрос: для подобных методов память выделяется дважды или один раз? Далее. Пытаясь справиться с этим, я заменил сигнатуру getHome() на это:
Правда, именно из-за этой ситуации я решил, что память выделяется дважды. Далее. Переделываем возвращаемое значение метода на указательное:
А если мы используем подобное в выражениях типа:
Стоп, а куда девается память, выделенная getHome()!? Она-ж зарезервирована! Утечка! Можно, конечно, сделать вот так:
И еще одно: сигнатуры некоторых методов из стандартной библиотеки для работы с std::string возвращают std::string&. Как они это делают? Создают новый указатель - т. е. выделяют в куче независимо от меня память? А иначе же lvalue... И мне ее потом очищать вручную? Собственно, как грамотно работать с std::string с точки зрения память, какие возращаемые типы указывать для подобных одномоментных функций, подобных указанной выше? Почему стандартные методы из std::string часто возвращают ссылку? Генерирует ли компилятор двойное выделение памяти (и, как следствие, копирование возвращаемого значения)? Зависит ли это от степени оптимизации? Что происходит при контакенции строк при использовании std::string - если создается новая строка, использующая новую память, как очищать предыдущие ненужные? Как вообще грамотно распределять память в подобных случаях? P. S. прошу заранее простить за несколько сумбурный и несколько несвязный стиль изложения.
0
|
01.05.2014, 16:30 | |
Ответы с готовыми решениями:
4
Ошибка terminate called after throwing an instance of 'std::bad_alloc' при работе с типом std::string Есть 4 потока. После осуществления блокировки барьером, 3 куда-то деваются, куда? (pthreads) Управление динамической памятью при работе с классами ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri |
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
01.05.2014, 16:58 | 2 |
Стоит пользоваться первым вариантом и не забивать себе голову до тех пор, пока не станет точно известно (например с помощью профилировщика), чтоузкоем место именно здесь.
Да, компилятор может создавать временный объект и производить лишнее копирование, но как правило современные компиляторы поддерживают RVO (Return value optimization, оптимизация возвращаемого значения), метод оптимизации как раз для подобных случаев.
1
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,304
|
|
01.05.2014, 17:06 | 3 |
Сообщение было отмечено relationer как решение
Решение
relationer, во-первых читай про RVO.
во-вторых есть техника COW. std::string ее не использует (в новом стандарте это явно запрещено, в старых не пользовалось популярностью), но можно создать свой класс с такой реализацией или использовать готовый. В третьих, в С++11 есть move semantics. А в предыдущих это реализуется вот этим паттерном. Так лучше не делать. Ибо безопасность исключений. Это надо каждый конкретный случай отдельно рассматривать. Нет. Давай конкретный пример - объясню. Нет. Зависит, если рассматривать твои первые примеры. Создается новая строка. Очищают память деструкторы. Вручную в данном случае ничего распределять не надо. Или тогда std::string не тот класс, который тебе нужен. "Грамотность" зависит от задачи и от результатов профилирования. Добавлено через 1 минуту Да, утечка. Не стоит так делать.
1
|
01.05.2014, 22:20 | 5 | |||||
Обычно через ссылку
0
|
01.05.2014, 22:20 | |
01.05.2014, 22:20 | |
Помогаю со студенческими работами здесь
5
Куда будет указывать указатель в std::map<string,pointer *>? Запись значения типа String^ в char* или std::string Куда деваются комментарии? Где и почему используют ту или иную строку std::string, char[], System::String^ ? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |