Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12

Передача строки в качестве параметра

07.06.2019, 16:31. Показов 8131. Ответов 66
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <string>
 
void test(const std::string& str)
{
    std::cout << str;
}
 
int main()
{
  test("Hello my dear friend!\n");
}
Что происходит?
Создаётся временный объект const std::string, конструктор которого принимает (и копирует в себя) const char*, вызывается функция test, затем объект уничтожается. Много лишних действий.

Можно ли сделать так, чтобы в EXE-шнике изначально хранился объект std::string, а не создавался перед вызовом функции?

p.s. В идеале – C++11, но если вариантов нет, рассмотрю что есть.

p.p.s. Интересен также вариант без создания промежуточных констант, если такое возможно, потому что, понятное, дело, можно сделать const std::string text = "Hello my dear friend!\n"; и подставлять её, но это неинтересно. Да и всё равно объект создаётся динамически.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.06.2019, 16:31
Ответы с готовыми решениями:

Передача функции в качестве параметра
Все привет. Помогите в решении следующей проблемы: есть класс XXX, один из методов которого принимает в качестве параметра указатель на...

Передача класса в качестве параметра
Здраствуйте, вообщем есть код class Main: public ExampleApplication { public: void createScene(void) { /* создаем...

Передача пути к файлу в качестве параметра через консоль
Доброго времени суток. Как в самой программе передать в качестве параметра путь к файлу? Понятное дело, что в консоли: путь до файла и...

66
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 16:34
Цитата Сообщение от Jin X Посмотреть сообщение
Можно ли сделать так, чтобы в EXE-шнике изначально хранился объект std::string, а не создавался перед вызовом функции?
Только объявить static const std::string'
В 17-ом стандарте появилась std::string_view - void test(const std::string_view& str)

Добавлено через 15 секунд
С ней этих проблем нет
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 16:41  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Только объявить static const std::string
Всё равно в EXE-шнике будет храниться ASCIIZ-строка, которая преобразуется в string.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
void test(const std::string_view& str)
Проблема в том, что string нужен для того, чтобы хранить строки, которые могут быть удалены. Иначе можно было бы вообще const char* использовать.

Например:
C++
1
2
3
4
5
void something(std::function<void()> func, const char* str)
{
  func();
  std::cout << str;  // но проблема в том, что func может удалить строку из памяти, и указатель str станет невалидным.
}
Такая же ерунда и со string_view, как я понимаю, может быть.

Добавлено через 31 секунду
Может, через constexpr как-то можно? Но constexpr std::string сделать не получится...
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 16:43
Цитата Сообщение от Jin X Посмотреть сообщение
Такая же ерунда и со string_view, как я понимаю, может быть.
Нет, не может. Для константных строк она всегда создаётся в compile-time

Добавлено через 43 секунды
Цитата Сообщение от Jin X Посмотреть сообщение
Всё равно в EXE-шнике будет храниться ASCIIZ-строка, которая преобразуется в string.
Ну да, она в любом случае должна там храниться
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 16:45  [ТС]
Т.е. если передаём const char*, то строка копируется, и пусть исходная удаляется, фиг с ней.
А если зашитую в код как константу, то никуда она не денется, можно и ссылку передать на оригинал.

Добавлено через 41 секунду
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Для константных строк она всегда создаётся в compile-time
Для константных, может, и создаётся, а если там будет переменная char* ?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 16:45
Цитата Сообщение от Jin X Посмотреть сообщение
Проблема в том, что string нужен для того, чтобы хранить строки, которые могут быть удалены. Иначе можно было бы вообще const char* использовать.
В смысле, кем они могут быть удалены?
Можешь const char * поставить, и сделать test(std::string("1111").c_str());
Пока функция test не завершится, строка не будет удалена.
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 16:46  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну да, она в любом случае должна там храниться
А почему сразу готовый объект не может храниться?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 16:48
Цитата Сообщение от Jin X Посмотреть сообщение
Для константных, может, и создаётся, а если там будет переменная char* ?
А какие там есть варианты?

Добавлено через 1 минуту
Цитата Сообщение от Jin X Посмотреть сообщение
А почему сразу готовый объект не может храниться?
Он и хранится. С тех пор, как появился constexpr, а может и раньше.
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 16:50  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В смысле, кем они могут быть удалены?
Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstring>
#include <functional>
 
void call(std::function<void()> func, const char* str)
{
  func();
  std::cout << str;  // но проблема в том, что func может удалить строку из памяти, и указатель str станет невалидным.
}
 
int main()
{
  char* s = new char[20];
  strcpy(s, "Hello World!");
  call([&s](){ strcpy(s, "Good bye!"); }, s);
  delete[] s;
 
  return 0;
}
Выдаст Good bye!, а не Hello World!
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 16:58
На самом деле, скорее всего для const std::string & и константы компилятор у тебя просто подставит эту константу в выражение

Добавлено через 1 минуту
Цитата Сообщение от Jin X Посмотреть сообщение
Выдаст Good bye!, а не Hello World!
Всё правильно - ты передаёшь адрес и изменяешь содержимое массива. Точно также ты и std::string можешь изменить в этой функции

Добавлено через 4 минуты
А, ну да, ты имел ввиду, что передашь c_str(), а потом изменишь std::string.
Ну, так делать плохо.
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 17:00  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Точно также ты и std::string можешь изменить в этой функции
Я могу объявить её вот так: void call(std::function<void()> func, const std::string str). Тогда мне будет по барабану на эти изменения.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 17:03
Цитата Сообщение от Jin X Посмотреть сообщение
Я могу объявить её вот так: void call(std::function<void()> func, const std::string str). Тогда мне будет по барабану на эти изменения.
Там точно не ссылка на std::string?
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 17:04  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну, так делать плохо.
ИМХО, плохо делать так не в лямбде, а в вызывающей функции. Т.е. когда изменение исходной передаваемой строки влечёт к изменению работы функции.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 17:07
Цитата Сообщение от Jin X Посмотреть сообщение
ИМХО, плохо делать так не в лямбде, а в вызывающей функции. Т.е. когда изменение исходной передаваемой строки влечёт к изменению работы функции.
Думаю, так плохо делать везде - передавать константную ссылку или указатель и изменять его втихую.
Но, способов писать плохие программы очень много и пытаться строить от них всех защиту - дело неблагодарное
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 17:10  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Там точно не ссылка на std::string?
Ну если будет ссылка, я же могу изменить исходную строку в func, и call выведет не то, что ей передали изначально. А если НЕ ссылка, то то, что передали.

Добавлено через 1 минуту
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Думаю, так плохо делать везде - передавать константную ссылку или указатель и изменять его втихую.
Если я пишу функцию, которой могут пользоваться другие, то проконтролировать изменения внутри вызываемой функции func я не могу, а внутри call – могу. В этом и суть.

Добавлено через 1 минуту
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Он и хранится. С тех пор, как появился constexpr, а может и раньше.
Так, я же не могу использовать constexpr вместе с std::string. Как быть?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 17:19
Цитата Сообщение от Jin X Посмотреть сообщение
Если я пишу функцию, которой могут пользоваться другие, то проконтролировать изменения внутри вызываемой функции func я не могу, а внутри call – могу. В этом и суть.
Думаю, лучше пусть это будут проблемы тех, кто пользуется. В данном случае ты жертвуешь производительностью, ради защиты от идиотов. причём пострадают все.

Добавлено через 5 минут
Цитата Сообщение от Jin X Посмотреть сообщение
Так, я же не могу использовать constexpr вместе с std::string. Как быть?
Не, здесь я имел ввиду constexpr-методы. Но, скорее всего, компилятор пока не умеет динамически выделять память в compile-time, поэтому std::string так не построить

Добавлено через 1 минуту
Само-собой он оптимизирует вызов - например, если в твоей функции будет вызываться только c_str() для параметра, то, думаю, даже объект не будет создаваться
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.06.2019, 18:02
Цитата Сообщение от Jin X Посмотреть сообщение
Если я пишу функцию, которой могут пользоваться другие, то
забей и не парься.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.06.2019, 18:08
Цитата Сообщение от Jin X Посмотреть сообщение
Проблема в том, что string нужен для того, чтобы хранить строки, которые могут быть удалены.
Как-то не стыкуется "могут быть удалены" и "чтобы в EXE-шнике изначально хранился объект".

Цитата Сообщение от Jin X Посмотреть сообщение
Для константных, может, и создаётся, а если там будет переменная char* ?
А так?
C++
1
2
3
4
5
6
7
8
9
10
void test(char * str)
{
    std::cout << str;
}
 
int main()
{
  static char str[] = "Hello my dear friend!\n";
  test(str);
}
В С++ есть два варианта инициализации объектов со static storage duration - статическая и динамическая. std::string "зашитый в exe" никак не может быть статически инициализирован, т.к. в нем используется динамическая память.

Если же речь о константе с automatic storage duration, то это такой же объект на стеке. Он живет в области видимости функции и будет создаваться каждый раз, когда поток управления дойдет до этого места.

Строковый литерал константен и имеет static storage duration, поэтому его как раз можно "зашить в exe".


Лучше опишите конкретно ту задачу, где вам это понадобилось.
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6812 / 2052 / 238
Регистрация: 14.12.2014
Сообщений: 4,305
Записей в блоге: 12
07.06.2019, 20:37  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Как-то не стыкуется "могут быть удалены" и "чтобы в EXE-шнике изначально хранился объект".
Всё стыкуется. Передавать можно разные данные. И константный объект, зашитый в EXE-шнике и ссылку на объект, который может быть удалён.

Цитата Сообщение от DrOffset Посмотреть сообщение
А так?
Что так? Не очень понял, к чему этот пример.

Цитата Сообщение от DrOffset Посмотреть сообщение
std::string "зашитый в exe" никак не может быть статически инициализирован, т.к. в нем используется динамическая память.
Хм. Звучит логично

Цитата Сообщение от DrOffset Посмотреть сообщение
Лучше опишите конкретно ту задачу, где вам это понадобилось.
Intel C++ Compiler выдаёт ремарки. В одной из них написал: value copied to temporary, reference to temporary used. И я подумал, что вероятно, можно сделать так, чтобы не было временных объектов. Он как раз написал при вызове с аргументом "строка" функции, которая принимает const std::string&. А ещё вот на такую строку тоже написал: std::this_thread::sleep_for(std::chrono::milliseconds(1000)); (причём, ткнул на число 1000).
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
07.06.2019, 20:55
Цитата Сообщение от Jin X Посмотреть сообщение
Intel C++ Compiler выдаёт ремарки. В одной из них написал: value copied to temporary, reference to temporary used. И я подумал, что вероятно, можно сделать так, чтобы не было временных объектов. Он как раз написал при вызове с аргументом "строка" функции, которая принимает const std::string&. А ещё вот на такую строку тоже написал: std::this_thread::sleep_for(std::chrono: :milliseconds(1000)); (причём, ткнул на число 1000).
Что-то здесь неправильно. Покажи код.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.06.2019, 20:55
Помогаю со студенческими работами здесь

Передача строки в качестве аргумента потоку
Создаю массив handle'ов HANDLE threads; Есть массив, состоящий из 5 символов &quot;ABCDE&quot; char symb; Создаю потоки...

Передача функции в качестве параметра
Как передать функцию с параметрами в transform? Т.е., например, мне надо из каждого числа вектора вычесть число k с помощью transform'а,...

Передача файла в качестве параметра
Как, в качестве параметра, передать функции файл и структуру??? Добавлено через 1 час 1 минуту Разве никто не знает???

Передача функции в качестве параметра
#include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; double f(double x) { return (2*x*x)-(exp(x)); double...

Передача CString в качестве параметра функции
Добрый всем вечер! Мучает один вопрос, на который не могу найти ответ. Как наилучшим образом передавать объект класса CString в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru