Многоликий const
Ключевое слово const — одно из самых многозначных в C++. Правильно использование const позволяет организовать множество проверок ещё на этапе компиляции и избежать многих ошибок из числа тех, которые бывает трудно найти при помощи отладчиков и/или анализа кода.
Первая половина заметки рассчитана скорее на начинающих (надеюсь мнемоническое правило поможет вам запомнить, где и для чего используется const), но, возможно, и опытные программисты смогут почерпнуть интересную информацию о перегрузке методов по const.
Константы и данные
Самый простой случай — константные данные. Возможно несколько вариантов записи:
const int i(1); int const j(1); int const k=1;
Все они правильные и делают одно и тоже — создают переменную, значение которой изменить нельзя.
const int k=1; k = 7; //Константы и указатели
При использовании const с указателями, действие модификатора может распространяться либо на значение указателя, либо на данные на которые указывает указатель.
Работает (const относится к данным):
const char * a = "a"; a="b";Тоже самое и тоже работает:
char const * a = "a"; a="b";А вот это уже не работает:
char * const a = "a"; a="b"; //Если бы операция присвоения изменяла бы не указатель, а данные:
*a = 'Y';то ситуация была бы диаметрально противоположной.
Существует мнемоническое правило, позволяющее легко запомнить, к чему относится const. Надо провести черту через "*", если const слева, то оно относится к значению данных; если справа — к значению указателя.
Ну и конечно, const можно написать дважды:
const char * const s = "data";Константы и аргументы/результаты функций
C функциями слово const используется по тем же правилам, что при описании обычных данных.
Константы и методы (перегрузка)
А вот с методами есть одна тонкость.
Во-первых, для методов допустимо использование const, применительно к this. Синтаксис таков:
class A < private: int x; public: void f(int a) const < x = a; // >;Кроме того, этот const позволяет перегружать методы. Таким образом, вы можете писать оптимизированные варианты методов для константных объектов.
И ещё… я собрался в отпуск… возможно, не смогу ответить на комментарии до понедельника-вторника. Не сочтите за невнимание 🙂
В чем разница const char* и char const*?
Подскажите почему выводится тип в формате char const * __ptr64 а не в том как обычно принято записывать const char* ?
Есть ли между ними хоть какая то разница и почему именно так?#include #include int main() < const char ch = 'a'; auto c_ptr = &ch; char const* another_c_ptr = &ch; std::cout
- Вопрос задан более года назад
- 454 просмотра
Комментировать
Решения вопроса 0
Ответы на вопрос 1
Developer, ex-admin
Между const char * и char const * - разницы нет. Допустимо использовать обе записи.
Но кроме самих данных, на которые указывает указатель, можно делать константным и сам указатель, как написал Adamos.
Ответ написан более года назад

gleendo @evgeniy8705 Автор вопроса
res2001 А есть какая то причина почему компилятор выводит запись именно в таком формате а не так как обычно пишут разработчики, т.е сначала const а потом char*

Я, на самом деле, был искренне уверен, что звездочка не играет и это обозначение константного указателя. Просто действительно никогда не сталкивался с такой "вывернутой" записью.
gleendo, Вообще без понятия.
К тому же от компилятора к компилятору строка, возвращаемая typeid().name() может различаться для одного и того же типа. И не факт, что в другом компиляторе const не будет указан в первой позиции.
Разработчики так пишут, видимо, потому что в книжках это наиболее частая запись. Но я встречал и второй вариант в реальных проектах.
Const char c что это
Что нужно. Как правильно копировать значение строк.
Re: Значение string в const char* как.
| От: | dilmah |
| Дата: | 11.05.11 08:04 |
| Оценка: |
Здравствуйте, Alexys, Вы писали:
A>День добрый!
A>Подскажите пожалуйста, как к const char* присвоить значение из string .
A>
A>const char* s_; A>for (int i = 0; i//2. шаг. (в дебагге s_ уже пустой ((( ) A> < A>char* value = "1"; A> string sValue(value); A> s_ = sValue.c_str(); A>> //1 шаг. (дебаггом смотрим, значение занеслом, переменная s_ содержит "1" A>
A>Что нужно. Как правильно копировать значение строк.
у тебя же sValue разрушается на каждой итерации цикла -- указатель который ты из него выделил c_str тоже перестает быть валидным
Re: Значение string в const char* как.
| От: | Uzumaki Naruto |
| Дата: | 11.05.11 08:05 |
| Оценка: |
1. Когда указываете указатеоль — это указатель — это адрес — адрес ячейки памяти — если его не проинициализировать — то он будет указывать х.з. знает куда.
2. Если есть указатель на блок памяти — то вполне логично, что нужно выделить под этот блок память — сделать это можно двумя пустями — на стеке — например char _s[255] или в куче malloc или char * _s = new char [255]
3. копирование строк осуществляется командой strcpy
итак из вашего кода мы получаем
char _s[2]; \\ два байта — первый под 1, другой под \0 — символ конца строки
const char* value = "1";
strcpy (&_s[0], value);
4. зачем вам цикл? что бы выполнить одну и туже операцию 5 раз ?

Re: Значение string в const char* как.
| От: | Valen |
| Дата: | 11.05.11 08:05 |
| Оценка: |
Здравствуйте, Alexys, Вы писали:
A>Что нужно. Как правильно копировать значение строк.
A>
A>std::string s_; A>for (int i = 0; i//2. шаг. (в дебагге s_ уже пустой ((( ) A> < A>char* value = "1"; A> string sValue(value); A> s_ += sValue.c_str(); A>> //1 шаг. (дебаггом смотрим, значение занеслом, переменная s_ содержит "1" A>
Если правильно понял, то нужно сделать deepcopy. или через string, или ручками выделить память для char* s_ и вызвать strcat.
Re[2]: Значение string в const char* как.
| От: | Alexys |
| Дата: | 11.05.11 08:08 |
| Оценка: |
Здравствуйте, Uzumaki Naruto, Вы писали:
UN>1. Когда указываете указатеоль — это указатель — это адрес — адрес ячейки памяти — если его не проинициализировать — то он будет указывать х.з. знает куда.
UN>2. Если есть указатель на блок памяти — то вполне логично, что нужно выделить под этот блок память — сделать это можно двумя пустями — на стеке — например char _s[255] или в куче malloc или char * _s = new char [255]
UN>3. копирование строк осуществляется командой strcpy
UN>итак из вашего кода мы получаем
UN>char _s[2]; \\ два байта — первый под 1, другой под \0 — символ конца строки
UN>const char* value = "1";
UN>strcpy (&_s[0], value);
UN>4. зачем вам цикл? что бы выполнить одну и туже операцию 5 раз ?
Цикл для наглядности.
Под циклом подразумевается хождение по N записям (или в бд или по xml, без разницы) и вытаскивать значения в переменную массива струткуры.
Просто облегчил, для наглядности минимальный пример.
Re: Значение string в const char* как.
| От: | kvser |
| Дата: | 11.05.11 08:08 |
| Оценка: |
Здравствуйте, Alexys, Вы писали:
A>День добрый!
A>Подскажите пожалуйста, как к const char* присвоить значение из string .
A>
A>const char* s_; A>for (int i = 0; i//2. шаг. (в дебагге s_ уже пустой ((( ) A> < A>char* value = "1"; A> string sValue(value); A> s_ = sValue.c_str(); /// s_ - указывает на внутренний массив sValue, который гарантированно не меняется до следующего вызова не константного члена A>> //1 шаг. после этого шага sValue уничтожается вместе со всеми своими внутренними данными A>
Используйте:
1) Можно использовать strcpy(s_, sValue.c_str()); В s_ будет записано sValue.size() байт + 1 для завершающего нуля.
2) Использовать sValue.copy(s_, sValue.size(), 0); После в s_ не будет завершающего нуля
Общий минус этих двух способов в том, что перед копированием необходимо следить, чтобы s_ указывало на выделенную память достаточного размера для размещения sValue.c_str();
3) Не использовать const char* s_, а обходитьяс только std::srting объектами.
Если необходимо затем вызывать синхронную(блокирующую)системную функцию, принимающую const char* s_, то передавать в нее конечное вычисленное значение sValue.c_str() Если вызываемая функция будет использовать данные в отдельном потоке, который может завершится прежде, чем для sValue будет вызван деструктор, то придется копировать.
Re[3]: Значение string в const char* как.
| От: | Uzumaki Naruto |
| Дата: | 11.05.11 08:13 |
| Оценка: |
const char ошибки
91. inline const char* Q_strrchr (const char *s, char c) < return strrchr( s, c ); >
92. inline int Q_strcmp (const char *s1, const char *s2) < return strcmp( s1, s2 ); >
93. inline int Q_stricmp( const char *s1, const char *s2 ) < return stricmp( s1, s2 ); >
94. inline const char* Q_strstr( const char *s1, const char *search ) < return strstr( s1, search ); >
95. inline char* Q_strupr (char *start) < return strupr( start ); >
96. inline char* Q_strlower (char *start) < return strlwr( start ); >
При компиляции выдает: strtools.h(91) : error C2440: return: невозможно преобразовать 'const char *' в 'char *'
1> В результате преобразования теряются квалификаторы
1>strtools.h(94) : error C2440: return: невозможно преобразовать 'const char *' в 'char *'
1> В результате преобразования теряются квалификаторы
Visual C++ 2008 Express Edition
Как зафиксить?
#1
17:17, 18 ноя 2010
13bit
А если через преобразование типа к (const char*)?
#2
17:22, 18 ноя 2010
#3
17:26, 18 ноя 2010
13bit
У меня компилируется ваш пример, без ошибок. Вы какой заголовочный файл подключаете для использования str* функций?
p.s. Не слушай нижнего товарища, который тебе предлагает какой-то недокод.
#4
17:26, 18 ноя 2010
13bit
Ну вот например у тебя есть так:
const char text1="Hello!"; char* text2=0;
И пишешь вот так:
text2=( char*)text1;
const char text1=0; char* text2="Hello!";
text1=( const char*)text2;
Может быть это совсем не то что тебе нужно, но мало ли.
#5
17:34, 18 ноя 2010
У меня здесь header-файл, вообще не понимаю откуда она тут лезет, эта ошибка.
#6
17:35, 18 ноя 2010
Это из краденной беты Source Engine. Просто хочу движок скомпилить и вот эта лабуда мешает.
#7
17:41, 18 ноя 2010
13bit
Прикол в том, что ты сам исправил уже, видимо :). То, что ты показал в первом посте, отличается от оригинального strtools.h, который я только что посмотрел. Ты же сам добавил const квалификаторы, как это нужно.
#8
17:47, 18 ноя 2010
Да, но почему всеравно дает ошибку? Может надо какие-нибудь дополнительные header \ lib файлы к солюшену прикрутить?
#9
17:54, 18 ноя 2010
#10
17:59, 18 ноя 2010
13bit
Там в отладочной сборке макросы подстановки срабатывают, т.е. ты пишешь Q_strstr, например, а компилятор заменяет этот вызов на вызов функции _Q_strstr, которая не была поправлена. Одно из решений - закомментировать вот этот код выше так:
#ifdef _DEBUG /* #define Q_memset(dest, fill, count) _Q_memset (__FILE__, __LINE__, (dest), (fill), (count)) #define Q_memcpy(dest, src, count) _Q_memcpy (__FILE__, __LINE__, (dest), (src), (count)) #define Q_memmove(dest, src, count) _Q_memmove (__FILE__, __LINE__, (dest), (src), (count)) #define Q_memcmp(m1, m2, count) _Q_memcmp (__FILE__, __LINE__, (m1), (m2), (count)) #define Q_strlen(str) _Q_strlen (__FILE__, __LINE__, (str)) #define Q_strcpy(dest, src) _Q_strcpy (__FILE__, __LINE__, (dest), (src)) #define Q_strrchr(s, c) _Q_strrchr (__FILE__, __LINE__, (s), (c)) #define Q_strcmp(s1, s2) _Q_strcmp (__FILE__, __LINE__, (s1), (s2)) #define Q_stricmp(s1, s2 ) _Q_stricmp (__FILE__, __LINE__, (s1), (s2) ) #define Q_strstr(s1, search ) _Q_strstr (__FILE__, __LINE__, (s1), (search) ) #define Q_strupr(start) _Q_strupr (__FILE__, __LINE__, (start)) #define Q_strlower(start) _Q_strlower (__FILE__, __LINE__, (start))*/ #else
#11
18:01, 18 ноя 2010
Я в Release компилировал.
#12
18:04, 18 ноя 2010
13bit
А кусок кода, который использует эти функции и который вываливается с ошибкой можешь показать? Просто твой приведенный пример верный.
#13
18:08, 18 ноя 2010
inline void Q_memset (void *dest, int fill, int count) < memset( dest, fill, count ); >
inline void Q_memcpy (void *dest, const void *src, int count) < memcpy( dest, src, count ); >
inline void Q_memmove (void *dest, const void *src, int count) < memmove( dest, src, count ); >
inline int Q_memcmp (void *m1, void *m2, int count) < return memcmp( m1, m2, count ); >
inline int Q_strlen (char const *str) < return strlen ( str ); >
inline void Q_strcpy (char *dest, char const *src) < strcpy( dest, src ); >
inline const char* Q_strrchr (const char *s, char c) < return strrchr( s, c ); >\\ на это ругается
inline int Q_strcmp (const char *s1, const char *s2) < return strcmp( s1, s2 ); >
inline int Q_stricmp( const char *s1, const char *s2 ) < return stricmp( s1, s2 ); >
inline const char* Q_strstr( const char *s1, const char *search ) < return strstr( s1, search ); >\\ тут тоже ругается
inline char* Q_strupr (char *start) < return strupr( start ); >
inline char* Q_strlower (char *start)
- Alexander K
- Постоялец
#14
18:12, 18 ноя 2010
Зачем возвращаемое значение const char* ? Поставь просто char*, а лучше посмотри что возвращают функции strrchr и strstr.