Приведение типа C с ключевым словом "const" - PullRequest
4 голосов
/ 06 августа 2010

Я обычно использую приведение типа C в коде C / C ++. Мой вопрос: означает ли что-либо добавление ключевого слова "const" в типе приведения к результату?

Например, я могу придумать несколько сценариев:

const my_struct *func1()
{
   my_struct *my_ptr = new my_struct;

   // modify member variables

   return (const my_struct *)my_ptr;
   // return my_instance;
}

В этом случае функция создает новый экземпляр структуры и преобразует его в постоянный указатель, поэтому вызывающая сторона не сможет дополнительно изменить свое внутреннее состояние, кроме как удалить его. Является ли приведение типа "const" обязательным, рекомендуемым или просто ненужным, поскольку любой оператор return работает.

В этом my_base является базовым классом my_derive.

const my_base *func2(const my_derive *my_ptr)
{
    return (const my_base *)my_ptr;
    // return (my_base *)my_ptr;
}

Поскольку my_ptr уже является указателем const, будет ли приведение его к (my_base *) включать const_cast для удаления const и другой неявный const_cast при возврате?

Есть ли причина добавлять "const" к целочисленному аргументу функции, поскольку его изменение никогда не влияет на состояние вне функции?

void func3(const int i)
{
    // i = 0; is not allowed, but why, as it is harmless?
}

Как насчет добавления "const" при приведении целого числа? Я думаю, что это должно напоминать func2().

void func4(short i)
{
    const unsigned int j = (const unsigned int) i;
    // const unsigned int j = (unsigned int) i;
}

Поправь меня, если я ошибаюсь. Учитывая, что приведение типов может быть часто задаваемым вопросом, я не уверен, дублирует ли это что-нибудь еще. Спасибо!

Ответы [ 3 ]

6 голосов
/ 06 августа 2010

Добавление ключевого слова const в тип приведения означает, что результат будет постоянным. Следующее не будет компилироваться в C ++ (в C это не имеет никакого эффекта):

int* x = (const int*)malloc(10); // cannot convert from 'const int *' to 'int *'

Вы действительно не должны использовать приведение типа C в вашем C ++ коде. Это небезопасно и должно использоваться только для совместимости с устаревшим кодом C. Вместо этого вы должны использовать приведение C ++.

В случаях, как в func3, обычно const квалификатор не используется. Нет большой причины добавлять квалификатор const к аргументу функции, если он не имеет указателя или не ссылается на тип. Учтите следующее:

void func3(      TYPE i);  // no reason to use `const`
void func3(const TYPE& i); // use `const`, so as not to accidentally change `i`

Когда вы назначаете lvalue для rvalue, как в func4, нет необходимости явно указывать квалификатор const в выражении приведения. Преобразование Lvalue в rvalue будет выполняться неявно в соответствии со стандартом C ++ 4.1.

5 голосов
/ 06 августа 2010

Добавление const к приведению аналогично добавлению const к любому другому спецификатору типа - результирующий объект - const.что это значит, зависит от контекста.Если вы добавите const на верхнем уровне (например, const int или const foo или int* const, то у вас просто будет объект const. В большинстве случаев его можно скопировать и назначить так же, как не-1009 ** объект может (хотя есть несколько исключений, например std::auto_ptr).

Если вы добавите const к указателю, то вы также можете добавить его к указанному типу. Например, int * const isconst указатель на обычный int, тогда как const int* или int const* - простой указатель на const int.

int i;
int* p = (int* const) &i; // fine; top-level const not a problem
int* p2 = (int const*) &i; // error; pointed-to object is const, so this is preserved
int const* p3= (int const*) &i; // OK

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

void func(int i); // forward-declare func
void func(const int i) // this matches the declaration
{
    // i is const here
}

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

Использование const в другом месте в объявлении параметра (например, в качестве части указателя) влияет на тип функции, как и при приведении.

1 голос
/ 06 августа 2010

В первом примере возвращение non-const в функции, для которой требуется const, снова его поймает, что означает, что const имеет значение, но вы не можете это заметить, потому что если его там нет, он будет добавлен.
Во втором примереэто будет один бросок, поддерживающий const.
В третьем примере он запрещен, потому что он безвреден: я изменю для остальной части функции и не подлежит восстановлению.
Имейте в виду, что помещение типа в контейнер не его типа будетприведите его автоматически, так как int, вставленное в длинное поле, не останется int.
Вы также должны помнить, что const означает то же самое, что и private или public для ассемблера, что является ничем.Сгенерированный код на ассемблере не будет отличаться вообще, независимо от того, куда вы положили const, и будет работать точно так же.

...