Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.91/108: Рейтинг темы: голосов - 108, средняя оценка - 4.91
Ksan
27 / 27 / 4
Регистрация: 02.11.2010
Сообщений: 370
#1

string, c_str

06.07.2012, 17:52. Просмотров 19652. Ответов 35
Метки нет (Все метки)

функция 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;
}

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

Так вот, собственно вопрос: зачем столько шумихи вокруг инкапсуляции, если даже в стринге ее легко обойти?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2012, 17:52
Ответы с готовыми решениями:

Буффер из std::string c_str()
Здравствуйте! такое дело: Проект на Qt5 и С++11. Есть форма с полем ввода....

Безопасность передачи string.c_str() в качестве параметра
Есть некоторая функция которая принимает в себя си-строку, модифицирует ее (в...

Не работает преобразование с c_str()
Доброго времени суток. Пытаюсь определить расширение найденного файла путем...

X=atof(s.c_str()); - ошибка в Builder10
Здравствуйте ! Помогите, пожалуйста, чайнику. Проблема такая: Создаю...

Visual c++ input().c_str() вводит мусор
Я создал стринг переменную, получил через getline cin значения, передал их в...

35
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.07.2012, 19:59 #21
diagon, Специализация шаблонной функции объявленной в классе своим типом, все же не совсем внутри класса.
0
Ksan
27 / 27 / 4
Регистрация: 02.11.2010
Сообщений: 370
06.07.2012, 20:06  [ТС] #22
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.07.2012, 20:08 #23
Ksan, Инкапсуляция. Я вам крайне советую почитать Герба Саттера. В коде, не относящемся к реализации класса (иерархии), используя его нормально (не используя хаки со специализациями и доступ к членам через смещение), вы можете использовать только public интерфейс класса, до private данных вам не дотянуться.
0
Avazart
Эксперт С++
7719 / 5628 / 549
Регистрация: 10.12.2010
Сообщений: 25,336
Записей в блоге: 17
06.07.2012, 22:45 #24
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
Да, если не предусмотрено "последействия" - т.е вы меняете переменну А, а она вызывает еще автоматом изменение переменной B ну и в тех случаях когда "односторонний" доступ к переменной (например только для записи)
0
_or_75
-1 / 0 / 1
Регистрация: 18.02.2012
Сообщений: 244
06.07.2012, 22:50 #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;
}
0
Evg
Эксперт CАвтор FAQ
19281 / 7138 / 528
Регистрация: 30.03.2009
Сообщений: 19,986
Записей в блоге: 30
07.07.2012, 00:29 #26
Цитата Сообщение от Ksan Посмотреть сообщение
Evg, ну то есть получается, что зря я храню характеристики персонажей в private?
Ведь проще напрямую взаимодействовать с переменными, чем через SetVal, GetVal
В маленьком проекте - проще. В большом проекте (особенно если над ним работает несколько человек) такой подход резко увеличивает вероятность того, что накосячишь на ровном месте, а потом концов не соберёшь. А потому лучше сразу приучать себя к тому, чтобы делать правильно

В функциях GetVal, SetVal ты всегда можешь поставить печать и быстренько посмотреть трассу изменения и чтения величины. Обращаясь к полю напрямую такого ты сделать не сможешь. Т.е. такой подход в том числе более удобен с точки зрения отладки
0
Avazart
Эксперт С++
7719 / 5628 / 549
Регистрация: 10.12.2010
Сообщений: 25,336
Записей в блоге: 17
07.07.2012, 00:32 #27
Ну и еще такой фактор как рост, сейчас-просто, а завтра- все равно придется писать SetVal,GetVal ( например, если появится последействие )
0
Evg
Эксперт CАвтор FAQ
19281 / 7138 / 528
Регистрация: 30.03.2009
Сообщений: 19,986
Записей в блоге: 30
07.07.2012, 00:35 #28
Есть ещё и такое явление: чтобы понять, как делать правильно, нужно хорошо наступить на грабли тогда, когда делаешь неправильно. Тогда будешь намного более чётко понимать, а нафига делают так
2
Avazart
Эксперт С++
7719 / 5628 / 549
Регистрация: 10.12.2010
Сообщений: 25,336
Записей в блоге: 17
07.07.2012, 00:40 #29
Ну честно говоря это действительно не удобно и не особо читаемо.
Например в Builder-е попровлено это дело свойствами.Но опять таки это ведь надстройка IDE, а не язык...
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
07.07.2012, 00:49 #30
Avazart, Все удобно и все читаемо, свойства это исключительно синтаксический сахар в большинстве случаев.
0
Avazart
Эксперт С++
7719 / 5628 / 549
Регистрация: 10.12.2010
Сообщений: 25,336
Записей в блоге: 17
07.07.2012, 00:52 #31
Возможно дело вкуса
C++
1
2
A->B= 10;
int i=A->B;
На мой взгляд смотрится лучше нежели
C++
1
2
A->SetB(10);
int i=A->GetB();
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
07.07.2012, 01:22 #32
На тему использования инкапсуляции. Представьте что вы написали код, в котором используется класс с открытыми полями, вот вы предоставили ваш код клиентам, клиенты вовсю используют вашу библиотеку, используют открытые поля и тут поступает просьба от клиентов или же вы сами решаете расширить функционал вашей программы и пишете код, который добавляет/удаляет поля в структуру или же переносит их в приватную область видимости структуры и пишите методы, которые работают с данными как-то по особенному, в зависимости от конкретного ТЗ, вот вы провели тесты, все хорошо, выкатываете обновление, клиенты обновляются... И вы получаете сотни гневных писем, т.к. после вашего обновления весь код который писали клиенты библиотеки придется переписывать! А теперь представьте, что вы сразу сделали доступ к элементам через интерфейс, а не напрямую, скольких бы проблем удалось избежать?
2
DU
1486 / 1132 / 164
Регистрация: 05.12.2011
Сообщений: 2,279
07.07.2012, 01:33 #33
Лучший ответ Сообщение было отмечено как решение

Решение

вот поучительный код для любителей нарушать правила:
http://liveworkspace.org/code/3d030d41e9cd8aa9e9ea195699a096fb
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 реализована с использованием оптимизации "копирование при записи". В восьмой студии строка без такой оптимизации сделана.
8
silent_1991
07.07.2012, 21:15
  #34

Не по теме:

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

0
DU
1486 / 1132 / 164
Регистрация: 05.12.2011
Сообщений: 2,279
07.07.2012, 21:43 #35
не силен в стандарте, но там это вроде не оговаривается. можно с такой оптимизацией, а можно и без нее. посмотрел в 2012 студии. там тоже такой оптимизации нет, а она уже с новым стандартом.
0
ValeryS
Модератор
7223 / 5485 / 683
Регистрация: 14.02.2011
Сообщений: 18,550
07.07.2012, 21:48 #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";
буфер одинаковый и новая память не выделяется
а просто переписываются значения в том же буфере
2
07.07.2012, 21:48
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.07.2012, 21:48

Очень медленное выполнение .c_str() в minGW
Есть функция: sscanf(line.c_str(), &quot;%d\t%d\t%hu.%hu.%hu\t%hu:%hu:%hu\t%lf&quot;,...

реализация функции c_str() в моем классе Str
Ребята, вот есть у меня в классе Str данные: private: Vec&lt;char&gt; data;...

c_str() или моя голова провалилась в пропасть
Здравствуйте товарищи, один и тот же код приводит меня к правильному решению в...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru