Какая польза от константных указателей (в отличие от указателей на константные объекты)? - PullRequest
28 голосов
/ 21 октября 2008

Я часто использовал указатели для создания объектов, например ...

const int *p;

Это просто означает, что вы не можете изменить целое число, на которое указывает p через p. Но я также видел ссылку на константные указатели, объявленные так ...

int* const p;

Насколько я понимаю, это означает, что переменная-указатель сама является константой - вы можете изменить целое число, на которое она указывает, в течение всего дня, но вы не можете указать на что-то другое. 1011 *

Какое возможное использование это будет иметь?

Ответы [ 11 ]

28 голосов
/ 21 октября 2008

Когда вы разрабатываете программы на C для встраиваемых систем или программы специального назначения, которые должны ссылаться на одну и ту же память (многопроцессорные приложения, совместно использующие память), вам нужны постоянные указатели.

Например, у меня есть 32-битный процессор MIP , к которому прикреплен маленький ЖК-дисплей . Я должен записать свои данные LCD на определенный порт в памяти, который затем отправляется на контроллер LCD.

Я мог бы # определить это число, но тогда мне также нужно привести его в качестве указателя, и компилятор C не имеет столько вариантов, когда я это делаю.

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

Например, для программ для ПК: если вы разрабатываете игры для DOS VGA (в Интернете есть учебники, которые интересно изучить, изучая основную низкоуровневую графику), то вам нужно записать в память VGA, на которую можно ссылаться как смещение от константного указателя.

-Adam

27 голосов
/ 21 октября 2008

Позволяет защитить указатель от изменения. Это означает, что вы можете защитить свои предположения, основываясь на том, что указатель никогда не изменяется, или от непреднамеренного изменения, например:

int* const p = &i;

...

p++;     /* Compiler error, oops you meant */
(*p)++;  /* Increment the number */
7 голосов
/ 21 октября 2008

другой пример: если вы знаете, где он был инициализирован, вы можете избежать будущих проверок NULL. Компилятор гарантирует, что указатель никогда не менялся (на NULL)…

6 голосов
/ 21 октября 2008

В любой неконстантной функции-члене C ++ указатель this имеет тип C * const, где C - это тип класса - вы можете изменить то, на что он указывает (т.е. его члены), но вы можете не изменяйте его, чтобы указать на другой экземпляр C. Для const функций-членов this имеет тип const C * const. Существуют также (редко встречающиеся) функции-члены volatile и const volatile, для которых this также имеет квалификатор volatile.

5 голосов
/ 21 октября 2008

Одно из применений - низкоуровневый (драйвер устройства или встроенный) код, в котором необходимо указать конкретный адрес, который сопоставлен с устройством ввода / вывода, например аппаратный вывод. Некоторые языки позволяют связывать переменные по определенным адресам (например, у Ada use at). В Си самый идиоматический способ сделать это - объявить постоянный указатель. Обратите внимание, что в таких случаях также должен быть указан квалификатор volatile.

В других случаях это просто защитное кодирование. Если у вас есть указатель, который не должен меняться , разумно объявить его так, чтобы он не мог измениться. Это позволит компилятору (и инструментам lint) обнаружить ошибочные попытки изменить его.

3 голосов
/ 21 октября 2008

Я всегда использовал их, когда хотел избежать непреднамеренного изменения указателя (такого как арифметика указателя или внутри функции). Вы также можете использовать их для паттернов синглтона.

'this' - это жестко закодированный постоянный указатель.

3 голосов
/ 21 октября 2008

То же, что и "const int" ... если компилятор знает, что он не изменится, это могут быть предположения об оптимизации, основанные на этом.

struct MyClass
{
    char* const ptr;
    MyClass(char* str) :ptr(str) {}

    void SomeFunc(MyOtherClass moc)
    {
         for(int i=0; i < 100; ++i)
         { 
                 printf("%c", ptr[i]);
                 moc.SomeOtherFunc(this);
         }
    }
}

Теперь компилятор может сделать немало для оптимизации этого цикла - при условии, что он знает, что SomeOtherFunc () не меняет значение ptr. С помощью const компилятор знает это и может делать предположения. Без этого компилятор должен предполагать, что SomeOtherFunc изменит ptr.

2 голосов
/ 21 октября 2008

Я видел некоторый OLE-код, в котором у вас был объект, переданный извне кода, и для работы с ним вы должны были получить доступ к конкретной памяти, в которую он был передан. Поэтому мы использовали указатели const, чтобы убедиться, что функции всегда манипулировал значениями, поступившими через интерфейс OLE.

1 голос
/ 21 октября 2008

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

У меня, конечно, нет данных, чтобы поддержать эту догадку, но я все равно сделаю ставку.

0 голосов
/ 21 октября 2008

Думайте о типе * и типе константы * как о самих типах. Затем вы можете понять, почему вы можете захотеть иметь const этих типов.

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