const - не должно ли это измениться - PullRequest
8 голосов
/ 28 января 2011

При запуске этого кода C ++ я ожидал, что результат будет Abc, но это было FFF, почему так? Разве name не указывает на постоянную char?

#include <iostream>
int main()
{
    const char* name = "Abc";
    name = "FFF";
    std::cout<<name<<std::endl;
    return 0;
}

Ответы [ 9 ]

14 голосов
/ 28 января 2011

Да, это указывает на const char, как вы говорите, но это не постоянный указатель. Вы меняете то, на что вы указываете, а не содержание того, на что вы указываете. Другими словами, память, содержащая «Abc», все еще содержит символы «Abc» после переназначения указателя.

Для постоянного указателя вы хотите const char* const name = "Abc";. В этом случае он не скомпилируется, так как вы не можете изменить то, на что указывает указатель.

В общем, с const и указателями в C ++ вы можете прочитать имя типа справа налево, чтобы понять, что происходит. Например, в случае const char* const вы можете прочитать это как «постоянный указатель на символьную константу». Немного странно, но это работает.

6 голосов
/ 28 января 2011

const char * name = "Abc";-> Неконстантный указатель-> имя, но данные (Abc) постоянны

name = "FFF" -> изменение указателя (имени) для указания FFF.

char *p              = "Hello";          // non-const pointer,
                                         // non-const data
const char *p        = "Hello";          // non-const pointer,
                                         // const data
char * const p       = "Hello";          // const pointer,
                                         // non-const data
const char * const p = "Hello";          // const pointer,
                                         // const data
3 голосов
/ 28 января 2011

Это известная проблема с const и носителями английского языка.

Синтаксис позволяет:

  • const T
  • T const

и оба имеют одинаковое значение.

Однако, как только вы бросаете указатель в миксе, это становится сложным:

  • const T* следует прочитать (const T)*
  • T const* следует читать (T const)*
  • T* const следует читать (T*) const

По этой причине я являюсь адептом всегда использоватьconst в непосредственной близости от объекта.Это более последовательно.

Обратите внимание, что та же проблема может быть обнаружена с typedef, давайте определим typedef T* pointer:

  • const pointer означает T* const, а не const T* (как предполагает макрос)
  • pointer const означает T* const, как текстовая замена

Если вы привыкли ставить const после имени,и не раньше, как прилагательное по-английски, тогда вы не попадете в эти ловушки.

3 голосов
/ 28 января 2011

С const char* name = "Abc"; вы говорите компилятору, что вы не будете изменять содержимое"Abc", используя name.Однако вы можете изменить указатель так, чтобы он указывал на другое место в памяти.Подробнее см. FAQ .

2 голосов
/ 28 января 2011

на самом деле самый правильный синтаксис -

char const * pName;

, потому что ключевое слово const применяется именно к части слева.

, если вы хотите, чтобы const poitner был constchar, вы бы написали это:

char const * const pName;

и указатель const на int;

int * const pInt;

PS: но я все равно пишу const в начале строки, когда могу,якорный привычка; -)

0 голосов
/ 05 февраля 2011

Литеральные строки "Abc" и "FFF" являются константой, но name является переменной (указатель на постоянные данные). Вы просто изменили переменную, чтобы она указала на разные постоянные данные.

Кроме того, в то время как в этом случае данные были обязательно постоянными, указатель на постоянные данные означает только то, что данные не могут быть изменены путем разыменования этого указателя, данные также могут быть изменены напрямую или через другой указатель. Э.Г.

int i = 0 ;
const int* p = &i ;
i++ ; // valid
(*p)++ // error.
0 голосов
/ 28 января 2011

Во-первых, const проверяется только во время компиляции. Если он компилируется, все операции будут выполняться нормально во время выполнения.

В вашем примере const относится к контенту, указанному name. Таким образом, вам разрешено изменять указатель, но не содержимое.

strcpy(name, "FFF");

будет отказано, но указатель не будет изменен, как вы.

0 голосов
/ 28 января 2011

Когда вы объявляете переменную как

const T* ptr = /*...*/

Вы объявляете указатель, говоря, что объект, на который указывает объект, а не указатель, не должен изменяться. Другими словами, это «указатель на T, который является постоянным».

Если вы хотите сделать невозможным переназначение указателя, вы можете написать

T* const ptr = /*...*/

Теперь это неизменный указатель на T, который можно изменить.

Вы можете объединить их вместе так:

const T* const ptr = /*...*/

Чтобы получить неизменный указатель на неизменный T.

В качестве забавного совета вы обычно можете определить, какие части пары указатель / указатель можно изменить, читая тип справа налево. Попробуйте это выше и посмотрите, что вы получите.

0 голосов
/ 28 января 2011
const char* name = "Abc";

На самом деле это означает, что name является указателем на данные const. Значит, это данные const, а не сам указатель . Так что это совершенно справедливо, если вы напишите:

name = "FFF"; //ok : changing the pointer

Однако, следующее не скомпилируется:

 char * const name = "Abc"; //const pointer to the non-const data!
 name = "FFF"; //error: trying to change the pointer itself!

См. Ошибка компилятора:

prog.cpp: 5: ошибка: присвоение переменная только для чтения ‘name’

Посмотрите здесь: http://www.ideone.com/KyNXx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...