о "int const * p" и "const int * p" - PullRequest
       0

о "int const * p" и "const int * p"

8 голосов
/ 11 марта 2011
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    int i1 = 0;
    int i2 = 10;

    const int *p = &i1;
    int const *p2 = &i1;
    const int const *p3 = &i1;

    p = &i2;
    p2 = &i2;
    p3 = &i2;

    cout << *p << endl
        << *p2 <<endl
        << *p3 <<endl;
    return 0;
}

Код может быть скомпилирован как с VC6.0, так и с VC2010. Но у меня есть вопросы, как удар:

const int * p = & i1;

Это означает, что точки "p" не могут быть изменены, но p не может быть изменено, я прав? так что

p = & i2;

эта строка может быть выполнена, да?

Эта строка:

int const *p2 = &i1;

По-моему, это означает, что p2 нельзя изменить, а какие точки p2 можно изменить, я прав? Почему

p2 = & i2;

можно скомпилировать?

Об этой строке:

const int const * p3 = & i1;

p3 = & i2;

О боже ... Я сумасшедший. Я понятия не имею, почему эта строка может быть скомпилирована без ошибок ... Может ли какое-нибудь тело помочь мне?

Еще один код, который меня смутил, здесь:

class Coo2    
{      
 public:     

 Coo2() : p(new int(0)) {}    

 ~Coo2() {delete p;}    


    int const * getP() const   
    {      
         *p = 1;         
         return this->p;      
    }      

 private:    
      int* p;    
};   

почему этот код можно скомпилировать? В

int const * getP () const

У меня есть значение или * p!

Ответы [ 8 ]

8 голосов
/ 16 ноября 2012

Здесь мы рассмотрим 4 типа объявлений указателей:

  1. int * w; Это означает, что w является указателем на целочисленное значение типа.Мы можем изменить как указатель, так и его содержимое.Если мы инициализируем w во время объявления, как показано ниже: int * w = &a;
    Тогда обе нижеприведенные операции являются жизнеспособными:
    w = &b; (true)
    *w = 1; (true)

  2. int * const x;
    Это означает, что x является постоянным указателем, который указывает на целочисленное значение типа.Если мы инициализируем x при объявлении, как показано ниже:
    int * const x = &a;
    Тогда мы не сможем сделать: x = &b;(wrong), потому что x является постоянным указателем и не может быть изменен.
    Однако это можно сделать: *x = 1;(true), поскольку содержание x не является постоянным.

  3. int const * y; // оба означают одно и то же
    const int * y;
    Это означает, что y является указателем, которыйуказывает на постоянное целочисленное значение.Если мы инициализируем y во время объявления, как показано ниже:
    int const * y = &a;
    Затем можно выполнить: y=&b;(true), потому что y является неконстантным указателем, который может указывать на что угодно.
    Однако мы не можемdo: *y=1;(wrong), поскольку переменная, на которую указывает y, является постоянной и не может быть изменена.

  4. int const * const z; // оба означают одно и то же
    const int * const z;
    Это означает, что z является постоянным указателем, который указывает на постоянное целочисленное значение.Если мы инициализируем z при объявлении, как показано ниже:
    int const * const z = &a;
    Следовательно, не указанные ниже операции являются жизнеспособными:
    z = &b;(wrong)
    *z = 1;(wrong)

5 голосов
/ 11 марта 2011

С помощью указателя вы можете сделать две вещи.

  1. Вы можете изменить данные, на которые они указывают, но не могут указать на другое место в памяти.
  2. Вы можете указать его в другом месте памяти, но не можете изменить данные, на которые он указывает.

Теперь, когда вы говорите, int const * ptr или int const * ptr, он попадает в первую категорию. Это так же, как -

const int num = 5; // Both mean the same.
int const num = 5; 

Чтобы фактически не иметь возможности перейти в другое местоположение, то есть указатель на постоянное местоположение, но иметь возможность изменять данные, семантика должна быть int* const. Поскольку содержимое указателя является константой, оно должно быть инициализировано при объявлении.

int num = 5;

int* const ptr; // Wrong
ptr = &num; // Wrong

int* const ptr = &num;
*ptr = 100;

Однако существует третий вид. Постоянный указатель на постоянное местоположение, которое не может ни указать на другое место в памяти, ни изменять данные, на которые оно указывает. (т.е. const int * const)

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

const int const *p3 = &i1;
p3 = &i2;  // Wrong

В приведенном выше фрагменте p3 - это постоянный указатель на постоянное местоположение. Таким образом, его нельзя изменить.

const в конце функции-члена говорит, что не собирается изменять состояние объекта. Когда вы говорите *p = 1;, вы не изменяете состояние объекта. p по-прежнему указывает на ту же ячейку памяти. Это не разрешено делать -

int const * Coo2::getP() const   
{      
     *p = 1;   // State of `p` is still not modified.
     p = new int ; // Error: Changing the memory location to which p points.
                   //        This is what changing the state of object mean and       
                   //        is not allowed because of `const` keyword at the end of function
     return this->p;      
}

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

4 голосов
/ 11 марта 2011

int const * p; и const int * p одинаковы. Это когда const идет после *, семантика выражения изменяется.

Я знаю, это безумие.

2 голосов
/ 11 марта 2011

Два абсолютно одинаковы. Имеет значение позиция классификатора относительно звездочки (*):

int const *p; // normal pointer to const int
const int *p; // ditto

int *const p; // const pointer to normal int (rarely useful)

int const * const p; // const pointer to const int
2 голосов
/ 11 марта 2011
const int *p = &i1;
int const *p2 = &i1;

Оба они объявляют неконстантные указатели для константных данных.

То есть, используя p, вы не можете изменять данные, на которые оно указывает.Однако вы можете изменить сам указатель, например, присвоив p = &i2, что допустимо.Но *p = 87987 недопустимо, так как данные, на которые указывает p, являются постоянными!

-

int * const p = &i1;

Это объявляет постоянный указатель на неконстантные данные.То есть p=&i2 недопустимо, но *p = 98789 допустимо.

-

const int * const p = &i1;

Это объявляет константный указатель на константные данные.То есть теперь и p=&i2, и *p=87897 являются незаконными.

1 голос
/ 07 октября 2013

Сжато;каждая комбинация чтения / записи int & pointer;

int main() {

  int a,b;

  int* w;                       // read/write int, read/write pointer
  w= &b;                        // good
  *w= 1;                        // good

  int* const x = &a;            // read only pointer, read/write int 
  // x = &b;                    // compilation error
  *x = 0;                       // good

  int const * y;                // read/write ptr, read only int 
  const int * y2;               // "    "    "
  y = &a;                       // good
  // *y = 0;                    // compilation error
  y2 = &a;                      // good
  // *y2 = 0;                   // compilation error

  int const * const z = &a;     // read only ptr and read only int 
  const int * const z2 = &b;    // "    "   "   "   
  // *z = 0;                    // compilation error
  // z = &a;                    // compilation error
  // *z2 = 0;                   // compilation error
  // z2 = &a;                   // compilation error

}   
1 голос
/ 11 марта 2011

int const * совпадает с const int *

1 голос
/ 11 марта 2011

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

  1. Если вы хотите указатель, который не может быть переназначен, вам нужно объявить его как Foo* const p = &bar;
  2. Если вы хотите указатель, который указывает на объект "const", которыйне может быть переназначен, объявите его как const Foo* const p = &bar

Это прекрасно, если указатель const int* foo назначен указателю const int* const bar, так же, как хорошо иметь *Значение 1014 * присваивается const int.Подумайте об этом точно так же.

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