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

#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 ответов


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

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

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

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

To, на самом деле не в состоянии изменить на другое местоположение, т. е. указатель на постоянное местоположение, но иметь возможность изменять данные, семантика должна быть 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 типа указателей объявления:

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

  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-это непостоянный указатель, который может указывать в любом месте.
    Однако, мы не можем сделать: *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)


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

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


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

эти оба заявляют, что не константный указатель на константные данные.

то есть, используя p, вы не можете изменить данные, которые он указывает. Однако вы можете изменить сам указатель, например, назначив as p = &i2, которое является законным. Но!--5--> является незаконным, так как данные p указывает на const!

--

int * const p = &i1;

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

--

const int * const p = &i1;

это объявляет указатель const на данные const. То есть теперь оба!--7--> и *p=87897 являются незаконными.


эти два точно такие же. Имеет значение положение классификатора относительно звездочки (*):

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

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

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

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


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


кратко; каждая комбинация чтения / записи 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

}