Форум программистов, компьютерный форум CyberForum.ru

string, c_str - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 110, средняя оценка - 4.68
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
06.07.2012, 17:52     string, c_str #1
функция string.c_str() возвращает const char*, что бы не изменяли строку напрямую. Но! Если явно преобразовать указатель к char*, то строка вполне изменяется.

C++
1
2
3
4
5
6
7
8
9
10
int main()
{
        string str = "qwerty";
        char *p = (char*)str.c_str();
        *(p+1) = 'k';
        
        cout << str;
        getch();
        return 0;
}

Угадайте что выведет.

Так вот, собственно вопрос: зачем столько шумихи вокруг инкапсуляции, если даже в стринге ее легко обойти?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
06.07.2012, 19:59     string, c_str #21
diagon, Специализация шаблонной функции объявленной в классе своим типом, все же не совсем внутри класса.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
06.07.2012, 20:06  [ТС]     string, c_str #22
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
06.07.2012, 20:08     string, c_str #23
Ksan, Инкапсуляция. Я вам крайне советую почитать Герба Саттера. В коде, не относящемся к реализации класса (иерархии), используя его нормально (не используя хаки со специализациями и доступ к членам через смещение), вы можете использовать только public интерфейс класса, до private данных вам не дотянуться.
Avazart
 Аватар для Avazart
6906 / 5146 / 253
Регистрация: 10.12.2010
Сообщений: 22,639
Записей в блоге: 17
06.07.2012, 22:45     string, c_str #24
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
Да, если не предусмотрено "последействия" - т.е вы меняете переменну А, а она вызывает еще автоматом изменение переменной B ну и в тех случаях когда "односторонний" доступ к переменной (например только для записи)
_or_75
-1 / 0 / 0
Регистрация: 18.02.2012
Сообщений: 244
06.07.2012, 22:50     string, c_str #25
а если так?

C++
1
2
3
4
5
6
7
8
9
int main()
{
        char *str = "qwerty";
        char *p = str.c_str();
        *(p+1) = 'k';
        cout << str;
        getch();
        return 0;
}
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16843 / 5264 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
07.07.2012, 00:29     string, c_str #26
Цитата Сообщение от Ksan Посмотреть сообщение
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
В маленьком проекте - проще. В большом проекте (особенно если над ним работает несколько человек) такой подход резко увеличивает вероятность того, что накосячишь на ровном месте, а потом концов не соберёшь. А потому лучше сразу приучать себя к тому, чтобы делать правильно

В функциях GetVal, SetVal ты всегда можешь поставить печать и быстренько посмотреть трассу изменения и чтения величины. Обращаясь к полю напрямую такого ты сделать не сможешь. Т.е. такой подход в том числе более удобен с точки зрения отладки
Avazart
 Аватар для Avazart
6906 / 5146 / 253
Регистрация: 10.12.2010
Сообщений: 22,639
Записей в блоге: 17
07.07.2012, 00:32     string, c_str #27
Ну и еще такой фактор как рост, сейчас-просто, а завтра- все равно придется писать SetVal,GetVal ( например, если появится последействие )
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16843 / 5264 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
07.07.2012, 00:35     string, c_str #28
Есть ещё и такое явление: чтобы понять, как делать правильно, нужно хорошо наступить на грабли тогда, когда делаешь неправильно. Тогда будешь намного более чётко понимать, а нафига делают так
Avazart
 Аватар для Avazart
6906 / 5146 / 253
Регистрация: 10.12.2010
Сообщений: 22,639
Записей в блоге: 17
07.07.2012, 00:40     string, c_str #29
Ну честно говоря это действительно не удобно и не особо читаемо.
Например в Builder-е попровлено это дело свойствами.Но опять таки это ведь надстройка IDE, а не язык...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
07.07.2012, 00:49     string, c_str #30
Avazart, Все удобно и все читаемо, свойства это исключительно синтаксический сахар в большинстве случаев.
Avazart
 Аватар для Avazart
6906 / 5146 / 253
Регистрация: 10.12.2010
Сообщений: 22,639
Записей в блоге: 17
07.07.2012, 00:52     string, c_str #31
Возможно дело вкуса
C++
1
2
A->B= 10;
int i=A->B;
На мой взгляд смотрится лучше нежели
C++
1
2
A->SetB(10);
int i=A->GetB();
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
07.07.2012, 01:22     string, c_str #32
На тему использования инкапсуляции. Представьте что вы написали код, в котором используется класс с открытыми полями, вот вы предоставили ваш код клиентам, клиенты вовсю используют вашу библиотеку, используют открытые поля и тут поступает просьба от клиентов или же вы сами решаете расширить функционал вашей программы и пишете код, который добавляет/удаляет поля в структуру или же переносит их в приватную область видимости структуры и пишите методы, которые работают с данными как-то по особенному, в зависимости от конкретного ТЗ, вот вы провели тесты, все хорошо, выкатываете обновление, клиенты обновляются... И вы получаете сотни гневных писем, т.к. после вашего обновления весь код который писали клиенты библиотеки придется переписывать! А теперь представьте, что вы сразу сделали доступ к элементам через интерфейс, а не напрямую, скольких бы проблем удалось избежать?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
07.07.2012, 01:33     string, c_str #33
Сообщение было отмечено автором темы, экспертом или модератором как ответ
вот поучительный код для любителей нарушать правила:
http://liveworkspace.org/code/3d030d...ea195699a096fb
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
int main()
{
  std::string str1 = "str";
  std::string str2 = str1;
 
  std::cout << "str1 = " << str1 << std::endl;
  std::cout << "str2 = " << str2 << std::endl;
 
  char* pStr1 = (char*) str1.c_str();
  pStr1[0] = 'x';
 
  std::cout << "str1 = " << str1 << std::endl;
  std::cout << "str2 = " << str2 << std::endl; // сюрприз
 
  return 0;
}
Output:
str1 = str
str2 = str
str1 = xtr
str2 = xtr // как же так. ведь эту строку не меняли.

Это происходит из-за того, что там std::string реализована с использованием оптимизации "копирование при записи". В восьмой студии строка без такой оптимизации сделана.
silent_1991
07.07.2012, 21:15
  #34

Не по теме:

DU, никогда не думал, что стандартный string copy-on-write реализует... В прошлом стандарте так же было?

DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
07.07.2012, 21:43     string, c_str #35
не силен в стандарте, но там это вроде не оговаривается. можно с такой оптимизацией, а можно и без нее. посмотрел в 2012 студии. там тоже такой оптимизации нет, а она уже с новым стандартом.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.07.2012, 21:48     string, c_str
Еще ссылки по теме:

C++ реализация функции c_str() в моем классе Str
C++ Идентификатор string не определён при наличии #include <string>
C++ Какое одинаковое значение можно вернуть из функций <string> f () и vector < <string> > f()?

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

Или воспользуйтесь поиском по форуму:
ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,061
07.07.2012, 21:48     string, c_str #36
Цитата Сообщение от Ksan Посмотреть сообщение
так это же указатели. Они в любом случае указывают на один и тот же массив
Цитата Сообщение от Schizorb Посмотреть сообщение
Ksan, да... но в первом случае (когда строки разной длины) они у меня указывают на разные. Компилятор gcc.
я думаю что это происходит так
C++
1
string str = "12345"
выделяется память на 6 байт
C++
1
const char *p1 = str.c_str();
указатель на эту память
C++
1
str = "abcdef";
а здесь уже нужно 7 байт
в старый не влазит
выделяем новую память
C++
1
const char *p2 = str.c_str();
указатель уже на неё
старую удаляем НО.. значения в ней остались
посему
C++
1
cout << p1 << '\n' << p2 << endl;
выводит два РАЗНЫХ участка памяти (хотя по мнению менеджера памяти первая уже свободна)
и если выделить память еще раз и что то записать то вполне вероятно что
p1 выведет не 12345 а что то другое
а при
C++
1
2
3
string str = "qwerty";
.............
str = "abcdef";
буфер одинаковый и новая память не выделяется
а просто переписываются значения в том же буфере
Yandex
Объявления
07.07.2012, 21:48     string, c_str
Ответ Создать тему
Опции темы

Текущее время: 23:13. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru