C ++ не констант к константной ошибке приведения - PullRequest
0 голосов
/ 24 февраля 2012

приведенный ниже код не компилируется

void aaa(const int **a) {
}

int *a[] = {new int[2]};
aaa(a);

Я получил "не могу преобразовать параметр 1 из 'int [1]" в "const int *" в VS2010 и аналогичную ошибку в gcc

когда я меняю декларацию на:

int const *a[] = {new int[2]};

или

const int *a[] = {new int[2]};

он компилируется, но я не понимаю, почему он не принимает объявление неконстантной переменной

Ответы [ 2 ]

8 голосов
/ 24 февраля 2012

Тип a равен int*[]; нужный тип int const**. int*[] преобразуется в int**, но неявно не преобразуется в int const**. Рассмотрим следующий код, чтобы понять, почему:

static int const ci = 42;

void aaa( int const** out )
{
    *out = &ci;
}

int
main()
{
    int* pa;
    aaa( &pa );     //  NOT LEGAL, because...
    *pa = 0;        //  would now change ci
    std::cout << ci << std::endl;
    return 0;
}

Как видите, разрешение на это преобразование будет нарушать const без требующий приведения.

В зависимости от того, что вы делаете, вы можете использовать:

void aaa( int const* const* out );

Неявное преобразование int** в int const *const * допустимо. (В противном случае вам понадобится где-то const_cast, чтобы сообщить компилятору что ты знаешь, что делаешь, и что это на самом деле не проблема.)

2 голосов
/ 24 февраля 2012

Функция aaa ожидает указатель на указатель на константу-int.Ваша переменная a является указателем на указатель на int.Присвоение последнего первому является ошибкой.

и int const *a[], и const int *a[] - это фактически одно и то же, что соответствует сигнатуре aaa.Если вы попробуете int * const a[], это будет другой тип (pointer-to-constant-pointer-to-int) и вы снова вызовете ошибку типа.

Если вы хотите, чтобы ваша функция aaaчтобы взять константу-указатель-на-указатель-на-int, нужно написать aaa(int ** const a), но постоянство значений параметров фактически не влияет на то, с чем вы можете вызывать.


Редактировать: "Но константность не добавляется неявным образом - делается с помощью неявного приведения? (Какой актуальный вопрос)"значение, которое вы передаете, например,

void aaa(const int a) {}

int b=5;
aaa(b);

... или указатель одного уровня

void aaa(const int* a) {}

int *b=new int;
aaa(b);

... но глубже добавить невозможно.Например, это неверно:

void aaa(const int** a) {}

int* b=new int;
int** c=&b;
aaa(c);

Я думаю, что Джеймс Канзе объясняет это намного лучше в своем ответе.

...