Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/114: Рейтинг темы: голосов - 114, средняя оценка - 4.64
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
1

std::string в char*

11.06.2012, 14:13. Показов 22323. Ответов 40
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Можно ли привести std::string к указателю на нуль-терминальную строку? Как?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.06.2012, 14:13
Ответы с готовыми решениями:

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri
на вод поступают 2 строки типа string. определить количество вхождений строки 2 в строку 1 ошибка...

ошибка в программе (cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*')
int main() { string fileName, currWord, currMax = &quot;&quot;; cin&gt;&gt;fileName; ...

Странная ошибка: [Error] no match for call to '(std::string {aka std::basic_string<char>}) (int&)'
У меня появляется проблема при компиляции сей программы: #include &lt;iostream&gt; #include &lt;string&gt;...

(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&
astxx::manager::connection::connection(std::basic_string&lt;char, std::char_traits&lt;char&gt;,...

40
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
11.06.2012, 14:17 2
string::c_str()
1
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
11.06.2012, 14:50  [ТС] 3
Думаешь, я не могу этого сам написать? Я имел ввиду готовый член. Он существует?
0
Заблокирован
11.06.2012, 14:56 4
Цитата Сообщение от taras atavin Посмотреть сообщение
Можно ли привести std::string к указателю на нуль-терминальную строку? Как?
Нельзя.

Но можно сделать эквивалентную по смыслу операцию:

C++
1
2
3
4
5
6
7
8
9
int main()
{
    std::string test("trololo");
 
    char* ptr = &test[0]; //получаем указатель на первый символ си-строчки
 
    std::cout<<ptr<<std::endl;
    return 0;
}
Но крайне не рекомендуется. Ибо нет никакой гарантии, что внутреннее хранилище стринга является непрерывным блоком памяти.
(разные реализации стандартной библиотеки могут по разному реализовывать std::string)

Безопасным способом является получение си-строки через метод: string::c_str()
Однако, данный метод обязан вернуть указатель на си-строку эквивалентную тому значению, что хранит в себе сам стринг. Это означает, что если стринг хранит данные не в непрерывном блоке памяти, то ему придётся выполнить ряд действий по созданию такого непрерывного блока памяти, чтобы предоставить указатель на него наружу, что приведет к падению производительности.

Если нужно гарантировать возможность быстрой работы, то можно использовать std::vector<char>, который исходя из ряда требований к контейнеру всегда хранит данные в непрерывном блоке памяти. И тогда запись:

C++
1
char* ptr = &test[0];
гарантированно будет валидна.
1
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
11.06.2012, 15:00  [ТС] 5
Цитата Сообщение от Bers Посмотреть сообщение
Безопасным способом является получение си-строки через метод: string::c_str()
Однако, данный метод обязан вернуть указатель на си-строку эквивалентную тому значению, что хранит в себе сам стринг. Это означает, что если стринг хранит данные не в непрерывном блоке памяти, то ему придётся выполнить ряд действий по созданию такого непрерывного блока памяти, что предоставить указатель на него наружу, что приведет к падению производительности.
Это разовая операция с достаточно короткой строкой, менее сотни символов, а времени на неё не жалко двух секунд. Требуется ли освобождать указатель, который вернёт string::c_str()?
0
Заблокирован
11.06.2012, 15:01 6
Цитата Сообщение от taras atavin Посмотреть сообщение
Думаешь, я не могу этого сам написать? Я имел ввиду готовый член. Он существует?
Можно унаследоваться от std::string и определить свой собственный operator char*()
И тогда приведение будет доступно без явного вызова c_str()

Добавлено через 41 секунду
Цитата Сообщение от taras atavin Посмотреть сообщение
Это разовая операция с достаточно короткой строкой, менее сотни символов, а времени на неё не жалко двух секунд. Требуется ли освобождать указатель, который вернёт string::c_str()?
Ни в коем случае. Данные являются собственностью стринга, а не вызывающей стороны.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
11.06.2012, 15:07 7
Да вот как раз таки нужно освобождать. c_str() генерирует строку, и возвращает указатель на нее. Если к примеру изменить сам объект std::string после генерирования этой строки, то последняя в свою очередь не изменится. Нужно удалять эту строку как любой другой массив
C++
1
delete [] ptr;
Добавлено через 1 минуту
Хотя нет, я поспешил, и скорей всего не прав.
1
Заблокирован
11.06.2012, 15:09 8
Цитата Сообщение от Toshkarik Посмотреть сообщение
Да вот как раз таки нужно освобождать. c_str() генерирует строку, и возвращает указатель на нее.
Хм... кстати.. а это вопрос:


Generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters.

A terminating null character is automatically appended.

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.

Нужно проверить, будет ли утечка.
Но вот сам лично я никогда не освобождал память, которую сам не создавал. И вроде бы утечек не было.


C++
1
2
3
4
5
6
7
8
9
10
int main()
{
    
    std::string test("trololo");
    const char* ptr = test.c_str();
 
   // delete [] ptr;  //если расскоментировать, получаем порчу памяти
 
    return 0;
}
итого: удалять стринговые данные нельзя
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
11.06.2012, 15:13 9
Строку, которую возвращает std::string::c_str() освобождать не только не надо, но и нельзя.
Ну и &test[0] для std::string не годится не только из-за возможной не непрерывности, но и потому, что строка не обязательно будет заканчиваться нулём. Скажем std::string::data() возвращает непрерываный блок, но нуля в конце там тоже не обещается, в отличие от c_str().
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
11.06.2012, 15:14  [ТС] 10
Цитата Сообщение от Bers Посмотреть сообщение
Ни в коем случае. Данные являются собственностью стринга, а не вызывающей стороны.
Ну я когда свой кривостринг делал, sting::operator char* возвращал копию. Соответственно нужен был delete.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
11.06.2012, 15:15 11
Цитата Сообщение от taras atavin Посмотреть сообщение
Ну я когда свой кривостринг делал, sting::operator char* возвращал копию.
Стандартный тоже может возвращать копию. Только копией этой владеет сам объект строки.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
11.06.2012, 15:17 12
Да, сгенерированная строка не меняется при изменении самого объекта. Нужно вызывать повторно функцию, чтоб изменилась и Си строка. Мысль про освобождение памяти - скорей всего выделенная память под строку освобождается при удалении объекта.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
11.06.2012, 15:20 13
Цитата Сообщение от Toshkarik Посмотреть сообщение
Да, сгенерированная строка не меняется при изменении самого объекта.
Этого, кстати, тоже никто не обещает. Результат c_str() можно считать валидным лишь до тех пор, пока для строки вызываются только константные функции.
1
Заблокирован
11.06.2012, 15:22 14
Цитата Сообщение от taras atavin Посмотреть сообщение
Ну я когда свой кривостринг делал, sting::operator char* возвращал копию. Соответственно нужен был delete.
Есть правило: кто память выделял, тот её и освобождает.
К тому же, тот кто выделял - тот знает точно: как он выделял. А значит лучше знает, как правильно освободить. Чего не скажешь о вызывающей стороне.

Единственное исключение из этого правила - это специализированные инструменты, которые управляют временем жизни объекта (всякие там смартпоинтеры).

Если придерживаться этого правила, то путаницы не возникает.
На примере std::string видно, что она этого правила придерживается.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
11.06.2012, 15:24  [ТС] 15
Это константа.
0
Higher
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
11.06.2012, 17:48 16
Цитата Сообщение от Toshkarik Посмотреть сообщение
Да, сгенерированная строка не меняется при изменении самого объекта. Нужно вызывать повторно функцию, чтоб изменилась и Си строка. Мысль про освобождение памяти - скорей всего выделенная память под строку освобождается при удалении объекта.
Разве?
А мне казалось, что возвращается указатель на строку в объекте. Например. Но здесь надо стандарт читать.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
11.06.2012, 18:22 17
Ну я вот так проверял. В любом случае и мой и Ваш варианты работают благодаря случаю. Как уже и сказали, строка действительна только до момента изменения самого объекта string.
0
Заблокирован
11.06.2012, 18:26 18
Цитата Сообщение от diagon Посмотреть сообщение
А мне казалось, что возвращается указатель на строку в объекте.
Я это так понимаю:
Если внутри стринга данные лежат в непрерывном блоке, то было бы странным создавать новый блок, копировать туда данные, и выдавать наружу его указатель.
Ведь с таким же успехом можно сразу выдать указатель на итак уже имеющийся блок.

Однако, поскольку стандарт не запрещает реализовывать внутренее хранилище по разному. То - не факт, что это будет именно так.

Другими словами, в отдельных случаях (реализациях стринга) это может работать. А в каких то может и не сработать. В этом и заключается смысл слова:
Цитата Сообщение от grizlik78 Посмотреть сообщение
Этого, кстати, тоже никто не обещает.
Может быть будет работать. Может быть не будет. Если нужно гарантированно портабельное решение, то лучше на такое не опираться.

Добавлено через 3 минуты
Цитата Сообщение от Toshkarik Посмотреть сообщение
Ну я вот так проверял. В любом случае и мой и Ваш варианты работают благодаря случаю. Как уже и сказали, строка действительна только до момента изменения самого объекта string.
Есть предположение, что:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
 
int main()
{
   std::string str = "12345";
   
   const char *cstr1 = str.c_str(),
              *cstr2 = 0;
   
   std::cout << str << '\n' << cstr1 << std::endl;
   
   str = "qwerty";
   
   cstr2 = str.c_str();
   
   std::cout << '\n' << str << '\n' << cstr1  //cstr1  выводит в режиме только для чтения мертвую память.
                << '\n' << cstr2 << std::endl;
   
   return 0;
}
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
11.06.2012, 18:26  [ТС] 19
Не пойму, зачем вы обсуждаете подобные связи? Вопрос копия/оригинал имеет смысл только в контексте делита.
0
Заблокирован
11.06.2012, 18:29 20
Pardon
0
11.06.2012, 18:29
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.06.2012, 18:29
Помогаю со студенческими работами здесь

Где и почему используют ту или иную строку std::string, char[], System::String^ ?
Где и почему используют ту или иную строку std::string, char, System::String^ ? Объясните...

char* vs std::string
При чтении чужих сорцов, обратил внимание, что в роли аргументов для функций/методов, как правило...

std::string и/или char*
Здравствуйте. пишу метод построчной обработки данных из файла Вот он: bool...

Преобразование std::string в char*
Несомненно, работать с определенным в STL классом string работать в разы приятнее, чем с обычным...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru