Почему следующее дает мне ошибку преобразования из двойного *** в постоянное двойное *** - PullRequest
2 голосов
/ 10 сентября 2009

Почему он не может конвертировать double *** в const double ***?

void foo(const double ***d)
{


}


int main (int args, char*[] args)
{
       double ***d;
       /*initialize d */

       foo(d);

}

Ответы [ 6 ]

8 голосов
/ 10 сентября 2009

Если верить вашему тегу C, gcc выдает предупреждение, так как типы различаются как для вашего примера, так и для const double * const * const * d. В C ++ это ошибка в коде OP, но подход slap-const -where допустим.

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

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

Более простой случай передачи T** в const T**, который показывает, почему это ошибка:

void foo ( const char ** z )
{
    *z = "A";
}


int main (int nargs, char** argv)
{
    char*   z = 0;
    char**  d = &z;

    // warning in C, error in C++
    foo ( d );

    // bad - modifies const data
    z[0] = 'Q';
}

const в C означает, что данные не изменятся. const в C ++ означает, что данные не будут изменяться публично - изменяемые данные в объекте C ++ могут изменяться. Компилятор AC может оптимизировать свой код так, чтобы он где-то кэшировал некоторые данные const, но компилятор C ++ не может этого сделать из-за возможной изменчивости, поэтому имеет более слабое ограничение: вы не можете возвращать данные const в неконстантные как указано выше. Таким образом, в C ++ double*** можно привести к const double * const * const * d, поскольку дополнительные const предотвращают возврат неизменяемой памяти, но в C он генерирует предупреждение и возможные ошибки, если компилятор оптимизирует повторный доступ к памяти в другом месте.

2 голосов
/ 10 сентября 2009

Ответ на ваш вопрос можно найти на http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17

Это означает, что вы действительно должны использовать const double * const * const * d.

0 голосов
/ 10 сентября 2009

С const double *** d только значение d равно const . В C допустимо преобразование из double a в const double * a , в то время как преобразование из double b в const double ** b (или дальнейшее косвенное указание) - нет.

Поэтому для преобразования из double *** d в const double *** d2 вы можете сделать следующее:

  double*** d;
  const double* b = **d;
  const double** c = &b;
  const double*** d2 = &c;

Конечно, использование const double *** d остается сомнительным из-за неконстантных косвенных указаний.

0 голосов
/ 10 сентября 2009

Рассмотрим d указатель на черный ящик.

Компилятор может добавить const либо к d, либо к самому чёрному ящику, но не к содержимому чёрного ящика. Так

void foo1(double ***d);        /* ok, no casts needed */
void foo2(double *** const d); /* ok, no casts needed; const added to `d` itself */
void foo3(double ** const *d); /* ok, no casts needed; const added to the blackbox */
void foo4(double * const **d); /* oops, trying to change the insides of the blackbox */
void foo5(const double ***d);  /* oops, trying to change the insides of the blackbox */
void foo6(double ** const * const d);
/* ok: d is a constant pointer to a constant blackbox */
0 голосов
/ 10 сентября 2009

Это также верно для ** (указатель на указатель) по тем же причинам.

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

   double d = 0.0;
   double * pd = &d;
   const double ** ppd = &pd; // <--- Error

Если бы вы могли это сделать, у вас мог бы быть «постоянный» указатель на данные (ppd), который вы могли бы изменить, изменив изменяемое значение d. Это нарушает const, поэтому компилятор не позволит вам сделать это.

0 голосов
/ 10 сентября 2009

использовать const_cast_operator ()

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