从int**到const int**的转换

Conversion from int** to const int**

本文关键字:int 转换 const      更新时间:2023-10-16

为什么我得到这个代码:

void foo ( const int ** );
int main() {
    int ** v = new int * [10];
    foo(v);
    return 0;
}
这个错误:

invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]|

我认为可以从非const转换为const。

这是因为您正在尝试从int** to const int**

转换
int ** v = new int * [10]; // v is int**
foo(v); //but foo takes const int**
  • int **是:"指向整数指针的指针"。
  • const int **是:"指向一个常量整数指针的指针"。

const的使用是一个契约,你不能通过两个引用的间接来满足这个契约。

来自标准:

const char c = 'c';
char* pc;
const char** pcc = &pc;   // not allowed (thankfully!)
                ^^^ here the bundit is hidden under const: "I will not modify"
*pcc = &c;                // *pcc is "pointer to const" right? so this is allowed...
*pc = 'C';                // would allow to modify a const object, *pc is char right?

所以可以修改const char 总是,只需使用上面的过程

也:

char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char * const*ps = a; // no error!

从下面的链接很好的引用:

通过类比,如果你把一个罪犯藏在合法的伪装下,他然后利用对伪装的信任。这是不好的。

http://www.parashift.com/c + + -faq-lite/constptrptr-conversion.html

与此相关的

也无效转换Derived** → Base**。如果转换Derived** → Base**是合法的,则可以对Base**进行解引用(生成Base*),并且可以使Base*指向不同派生类的对象,这可能导致严重的问题。明白为什么:

class Vehicle {
public:
  virtual ~Vehicle() { }
  virtual void startEngine() = 0;
};
class Car : public Vehicle {
public:
  virtual void startEngine();
  virtual void openGasCap();
};
class NuclearSubmarine : public Vehicle {
public:
  virtual void startEngine();
  virtual void fireNuclearMissle();
};
int main()
{
  Car   car;
  Car*  carPtr = &car;
  Car** carPtrPtr = &carPtr;
  Vehicle** vehiclePtrPtr = carPtrPtr;  // This is an error in C++
  NuclearSubmarine  sub;
  NuclearSubmarine* subPtr = ⊂
  *vehiclePtrPtr = subPtr;
  // This last line would have caused carPtr to point to sub !
  carPtr->openGasCap();  // This might call fireNuclearMissle()!
  ...
}

http://www.parashift.com/c + + -faq-lite/derivedptrptr-to-baseptrptr.html

考虑:

class Vehicle {
public:
  virtual ~Vehicle() { }
  virtual void startEngine() = 0;
};
class Car : public Vehicle {
public:
  virtual void startEngine(){printf("Car engine brummmn");}
  virtual void openGasCap(){printf("Car: open gas capn");}
    virtual void openGasCap2(){printf("Car: open gas cap2n");}
      virtual void openGasCap3(){printf("Car: open gas cap3n");}
            virtual void openGasCap4(){printf("Car: open gas cap4n");}
}; 
class NuclearSubmarine : public Vehicle {
public:
    int i;
  virtual void startEngine(){printf("Nuclear submarine engine brummmn");}
    virtual void fireNuclearMissle3(){printf("Nuclear submarine: fire the missle3!n");}
    virtual void fireNuclearMissle(){printf("Nuclear submarine: fire the missle!n");}
  virtual void fireNuclearMissle2(){printf("Nuclear submarine: fire the missle2!n");}
};   
int main(){
  Car   car; Car*  carPtr = &car;
  Car** carPtrPtr = &carPtr;
  //Vehicle** vehiclePtrPtr = carPtrPtr;  // This is an error in C++, But:
  Vehicle** vehiclePtrPtr = reinterpret_cast<Vehicle**>(carPtrPtr);
  NuclearSubmarine  sub; NuclearSubmarine* subPtr = &sub;
  *vehiclePtrPtr = subPtr; // carPtr points to sub !
  carPtr->openGasCap();  // Nuclear submarine: fire the missle3!
  carPtr->openGasCap2();  // Nuclear submarine: fire the missle!
  carPtr->openGasCap3();  // Nuclear submarine: fire the missle2!
  //carPtr->openGasCap4();  // SEG FAULT 
}

如果您从cv限定符的第一个差异开始在所有级别添加const,则只能在类似指针类型之间的转换中添加const限定符。

因此,您可以将int**转换为int const* const*,但不能转换为int const* *。如果允许省略在中间级别添加const,则可以这样做:

const int c = 29;
int *pi;
const int** ppci = &pi; // only adding const, right
*ppci = &c;
*pi = 0; // changing c ?! but no const_cast in sight

您在这里被c++令人困惑的指针解析规则误导了。这样看可能更清楚:

typedef const int * ptr_to_const_int;
void foo( ptr_to_const_int *);
int main() {
    int ** v = new int * [10];
    foo(v);
    return 0;
}

foo()的形参列表承诺的是,你将向它传递一个指向(指针到常量的东西)的指针。但是new int*[10]意味着"指向(指向非常量的指针)"。

如果foo是这样定义的:

foo( const int **p )
{
  (*p); //<-- this is actually of type const int *
}

而我认为你在期待

foo( const int **p )
{
  (*p); //<-- you're expecting this to be of type int *
  p = 0; //<-- and this to throw a compiler error because p is const
}

但是你声明为常量的不是p,而是它所指向的东西

无论如何,只要在这种情况下使用typedef,一切都将清晰可读。