Const-правильность и неизменяемость выделенных объектов - PullRequest
5 голосов
/ 22 октября 2010

Во время недавнего обсуждения (см. Комментарии к этому ответу ) Р. рекомендовал никогда не создавать псевдонимы для типов указателя на const, поскольку вы не сможете освободить ссылочные объектылегко в соответствующей C-программе (помните: free() принимает аргумент указателя, не являющийся const , а C99 6.3.2.3 допускает только преобразование из неквалифицированного в квалифицированное ).

Язык C, очевидно, предполагает существование владельца для любого выделенного объекта, т.е. кто-то где-то должен хранить не-1010 * указатель на объект, и этот кто-то отвечает за освобождение.

Теперь рассмотрим библиотекувыделение и инициализация объектов, которые нельзя изменить из кода пользовательского пространства, поэтому вызовы функций всегда возвращают const -квалифицированные указатели.

Очевидно, что библиотека является владельцем объекта и должна сохранять не- *Указатель 1016 *, что несколько глупо, так как пользователь уже предоставляет совершенно правильную, но const копию указателя при каждом вызове библиотеки.

Чтобы освободить такой объект, библиотека должна отбросить спецификатор const;насколько я могу судить, следующее

void dealloc_foo(const struct foo *foo)
{
    free((void *)foo);
}

является действительным C;он был бы недействительным только в том случае, если бы параметр foo был дополнительно restrict -квалифицирован.

Однако отбрасывание const выглядит несколько взломанным.

Есть ли другой способ, кромеотбрасывать const из всех возвращаемых значений библиотечных функций, что потеряло бы любую информацию об изменчивости объекта?

Ответы [ 3 ]

4 голосов
/ 23 октября 2010

Я не читаю то же самое в 6.3.2.3.Этот параграф о конверсиях, которые происходят неявно и не нуждаются в приведениях.Поэтому неявное преобразование из объекта указателя на const может быть запрещено, но это ничего не говорит о явном приведении.

Приведения обрабатываются в 6.5.4, и я не вижу ничего, что могло бы ограничить вас от приведения любого указателя на const, который сам по себе не const квалифицирован как (void*),Напротив, он говорит, что

Преобразования, в которых используются указатели, отличные от тех, которые разрешены ограничениями 6.5.16.1, должны указываться посредством явного приведения.

Поэтому я прочитал там, что если вы делаете вещи явно, они разрешены.

Так что я думаю, что следующее полностью допустимо

char const *p = malloc(1);
free((void*)p);
Какие 6.5.4 орбиты будут следующими char * constр = маллок (1);бесплатно ((недействительными *) р);/ * выражение приведено с константной квалификацией * /

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

  • библиотека возвращает указатель на внутренний объект, затем она должна квалифицировать его как указатель на const, чтобы иметь некоторую слабую защиту, чтобы вызывающий не изменял его, либо
  • библиотека возвращает недавно выделенный объект, который входит в обязанности вызывающей стороны.Тогда его не должно волновать, изменяет ли его вызывающий объект, поэтому он может возвращать указатель на неквалифицированный объект.Если вызывающий затем хочет убедиться, что содержимое не было случайно перезаписано или что-то еще, он может назначить его указателю const, для его использования.
2 голосов
/ 22 октября 2010

Если объект действительно неизменный, зачем давать пользователю указатель на него и рисковать возможностью испортить объект? Сохраните адрес объекта в таблице, верните непрозрачный дескриптор (целочисленный индекс таблицы?) Пользователю и примите этот дескриптор в подпрограммах вашей библиотеки.

1 голос
/ 23 октября 2010

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

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