2016-04-08 2 views
1

В настоящее время я пытаюсь изучить некоторые C++ и наткнулся на следующее неинтуитивное поведение. Поскольку t является указателем на const int, я бы ожидал, что *t останется таким же, если мы не изменим t.Почему постоянный целочисленный указатель указывает на недопустимое целое число?

#include <iostream> 
using namespace std; 
int main(int argc, char *argv[]) 
{ 
    int a = 3; 
    const int* t = &a; //Why is this allowed? a is NOT const int 
    a = 4; 
    cout << *t << endl; //This does then print 4 
    //*t = 4; //Throws error. 

    return 0; 
} 

Может кто-нибудь объяснить, почему это происходит?

+0

, чтобы устранить путаницу, которую я предлагаю начать без указателей. 'int a = 1; const int b = a; 'просто отлично, а теперь' b' является const, а 'a' - нет, даже если удержание того же значения – user463035818

+0

@ tobi303 Да, но в вашем примере' b' получает * копию * значение 'a'. – flawr

+1

ну, тогда как насчет 'int a = 1; const int & b = a; 'now' b' является ссылкой для 'b', но вы не можете изменить значение через' b', даже если 'a' не const const – user463035818

ответ

3

В т представляет собой указатель на const int я ожидал бы *t остаться такой же, пока мы не изменим t.

Вы не можете сделать это предположение в общем, потому что t может указывать на объект, не являющийся объектом const, например, в вашем примере.

const int* t = &a; //Why is this allowed? a is NOT const int 

Может кто-нибудь объяснить, почему это делает компиляции?

Правила C++ позволяют неявное преобразование T* в const T*. Это разрешено, потому что очень полезно иметь указатель-на-const (или ссылку) на неконстантный объект. Указатель на const просто означает, что объект не может быть изменен «через» указатель. Сам объект может быть const или не const.

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

+0

Спасибо за это объяснение! T имеет смысл теперь, когда вы думаете о типе как о том, что вы можете делать * через * эту точную переменную. – flawr

4

const int* t только что означает, что вы не можете изменить значение t, ссылаясь на t, ничего более. Первоначальное значение может быть изменено, но оно не имеет никакого отношения к ответственности t.

Если вы хотите, чтобы значение не будет изменен, вы должны позволить t пункта константного, таким как

const int a = 3; 
const int* t = &a; 

И в этом случае, вы не можете сделать точку int* указателя на Это.

int* t = &a; // error 
+0

Это имеет смысл. Я ожидал, что 'const int *' может принимать только адреса в 'const int'! – flawr

+0

@flawr 'int *' может быть неявно введено в 'const int *', это просто означает, что вы не измените значение через него. Например, вы можете передать функцию 'int *' для функции, если вы не измените значение внутри функции, вы можете заставить эту функцию воспринимать 'const int *' как параметр. – songyuanyao

-4

const int* t = &a; // int* or const int* can assgin to const int*

0

t Как это указатель на const int я ожидал бы *t остаться такой же, пока мы не изменим t.

Ответ прост: const ключевое слово в объявлении типа указателя не означает, что "это константа, а" вы не можете изменить его.

Это полезно, например, когда вы создаете переменную, а затем вызвать другую функцию, чтобы сделать что-то с ним, но вы хотите запретить изменение:

extern int countZerosInArray(const int *array, int arrayLen); 

    int myVariableArray[ 100 ]; 
    // ... fill the array - i.e. modify it! 
    int noOfZeros = countZerosInArray(myVariableArray, 100); 

countZerosInArray функция сказал он доступ только для чтения к массиву, хотя сам массив, конечно, не является постоянным.

Смежные вопросы