Констанстный указатель на константу?
Что-то я запутался(
void Ge(wchar_t* buffer, size_t size) {
wchar_t const* const message = L"Test Message!";
std::cout << typeid(message).name() << std::endl;
std::cout << "b: " << (const void*)message << std::endl;
wcscpy_s(buffer, size, message);
}
wchar_t const* const message - широкосимвольный константный указатель на константу ? Или это указатель на константный объект типа whar_t?
Очень похоже на пример, ниже, когда не только само значение указателя является константой, но сам указатель не может менять свой адрес в памяти, т.к.
void print(const int* const x) // константный указатель на константу
{
int z{2};
//x = &z; // значение указателя нельзя изменить
std::cout << "z = " << z << std::endl; // z = 2
std::cout << "*x = " << *x << std::endl; // *x = 10
}
Правильней будет сказать что это константный указатель который не может менять свой адрес в памяти и по этому адресу лежит константное значения типа wchar_t? Подскажите)
Ответы (3 шт):
Неизменный указатель (сам адрес не меняется) на память без возможности писать (данные в памяти не меняются):
// указатель message никогда не будет
// указывать в другое место
// -------------
wchar_t const* const message
// -------------
// указатель нельзя использовать
// для изменения значений в памяти
// `wchar_t const` и `const wchar_t` взаимозаменяемы
P.S. Объявление параметра константным в прототипе функции не меняет прототип:
void print(const int* const x) // эти два прототипа
void print(const int* x) // ничем не отличаются
Поэтому при объявлении функции хороший тон не указывать const, а реализации вы вольны его использовать:
void print(const int* x); // в объявлении const не пишут
...
void print(const int* const x) { // в реализации можно писать
// ...
}
Все что до первой */(/... или до имени переменной (смотря что встречается первым) может быть в любом порядке.
const int x = 42; = int const x = 42;
const int *const x = int const *const x
Очень похоже на пример, ниже, когда не только само значение указателя является константой, но сам указатель не может менять свой адрес в памяти
Да, это оно и есть.
Еще, обратите внимание что typeid отбрасывает константность, так что для wchar_t const* const он выведет wchar_t const* (отбрасывается только константность самого указателя, а не того, на что он показывает).
Вместо этого есть такой трюк:
template <typename T>
void PrintType()
{
std::cout <<
#ifdef _MSC_VER
__FUNCSIG__
#else
__PRETTY_FUNCTION__
#endif
<< '\n';
}
А потом PrintType<decltype(message)>();. Это выводит настоящий тип.
Есть очень простое правило:
const всегда относится к вещи левее него
Таким образом:
char const * foo = &v1; // изменяемый указатель на постоянное значение;
foo = &v2; // OK указатель можно перенаправить, но значение куда
*foo = 'x'; // ERROR он указывает нельзя изменить
char * const bar = &v1; // постоянный указатель на изменяемое значение;
bar = &v2; // ERROR его нельзя перенаправить после инициализации,
*bar = 'x'; // OK но через него можно изменить значение
char const * const baz = &v1; // постоянный указатель на постоянное значение
baz = &v2; // ERROR нельзя перенаправить
*baz = 'x'; // ERROR и нельзя изменить значение
У этого правила есть одно исключение:
Если const находится первым, то он относится к вещи правее него
То есть:
const char * qux; // эквивалентно выражению `char const * foo`
Демонстрация: godbolt