简体   繁体   English

从char * *变量分配给char * const *变量-为什么允许它?

[英]Assigning to a char * const * variable from a char * * variable - why is it allowed?

I am surprised that the following behavior of C++ (Visual Studio 2012 compiler). 我对C ++(Visual Studio 2012编译器)的以下行为感到惊讶。

char * * PointerToPointerToChar = NULL;
char * const * PointerToConstPointerToChar = NULL;
char const * * PointerToPointerToConstChar = NULL;

PointerToPointerToConstChar = PointerToPointerToChar; // Assignment 1: Gives compiler error as I would expect
PointerToConstPointerToChar = PointerToPointerToChar; // Assignment 2: NO COMPILER ERROR ???

PointerToPointerToChar = PointerToPointerToConstChar; // Assignment 3: Gives compiler error as I would expect
PointerToPointerToChar = PointerToConstPointerToChar; // Assignment 4: Gives compiler error as I would expect

I understand the const keyword in C++, specifically how it's placement affects what is considered const (the entity to the left). 我了解C ++中的const关键字,尤其是它的位置如何影响const(左侧的实体)。

It seems like the compiler tries to protect the user of the RHS variable from a const-stripping alias at either level of indirection (assignments 3 and 4). 似乎编译器试图在任一间接级别 (分配3和4)保护RHS变量的用户免受const剥离别名的影响。 But the LHS is only protected from a const-stripping alias at one level of indirection (assignment 1) and not the other level of indirection (assignment 2). 但是LHS仅在一个间接级别(分配1)而不在另一个间接级别(分配2)受到保护,免受const剥离别名的侵害。 In other words, given that the following is prevented by the compiler 换句话说,假设编译器阻止了以下操作

PointerToPointerToConstChar = PointerToPointerToChar; // Assignment 1: Gives compiler error as I would expect
PointerToPointerToChar[0][0] = 'A'; // The user of the LHS variable was effectively lied to about the constness of the *characters* - second level of indirection

then why isn't the following also prevented by the compiler 那么为什么编译器也无法阻止以下操作

PointerToConstPointerToChar = PointerToPointerToChar; // Assignment 2: NO COMPILER ERROR ???
PointerToPointerToChar[0] = NULL; // The user of the LHS variable was effectively lied to about the constness of the *pointers* - first level of indirection

Is this correct C++, and if so what is the rationale? 这是正确的C ++吗?如果是,则依据是什么? It seems inconsistent. 似乎不一致。 Thanks! 谢谢!

The type const* doesn't mean the value won't change, it means you can't change it using that pointer. type const*并不意味着该值不会改变,这意味着您无法使用该指针进行更改。


Because if you could do that, you could assign to the *PointerToPointerToConstChar any const char* - while PointerToPointerToChar relies on it being normal char* . 因为如果可以这样做,则可以将任何const char*分配给*PointerToPointerToConstCharPointerToPointerToChar依靠它为普通char* If that was allowed: 如果允许的话:

PointerToPointerToConstChar = PointerToPointerToChar; // assume PointerToPointerToChar is pointing to a valid memory block
const char str[] = "Hello world!";
*PointerToPointerToConstChar = str;
(*PointerToPointerToChar)[0] = 'X'; // Oops, we just modified a const array

Assigning a char** to a char* const* is analogous to assigning a char* to a const char* . char**分配给char* const*类似于将char*分配给const char* It makes perfect sense. 这是很合理的。

char array[] = "foo";
char* ptr1 = array;            // Can change array through ptr1
char const* ptr2 = ptr1;       // Can't change array through ptr2

Use of char** and char* const* complicates what can and what can't be changed a bit more. 使用char**char* const*使可以更改和不能更改的内容更加复杂。

char** ptrptr1 = &ptr1;

// Can change where ptr1 points to through ptrptr1
*ptrptr1 = <some other char*>; // OK

// Can change the value of what ptr1 points to through ptrptr1.
(*ptrptr1)[0] = 'x';           // OK

char* const* ptrptr2 = ptr1;

// Can't change where ptr1 points to through ptrptr2
*ptrptr2 = <some other char*>; // Not OK

// Can change the value of what ptr1 points to through ptrptr2.
// (*ptrptr2) is still of type 'char*'.
(*ptrptr2)[0] = 'x';           // OK

You have a Pointer to something that is const . 您有一个指向const的指针。 The pointer is not const , just what it points to. 指针不是const ,而是它指向的内容。 You assign to that pointer a pointer to something that is not const . 您可以为该指针分配一个指向非const的指针。 That is fine. 那也行。 The pointer is not const and the const in this case just tells us, that the object pointed to will not be changed through this pointer . 指针不是const,在这种情况下const只是告诉我们,指向的对象不会通过此指针更改。 It doesn't have to be const anywhere else. 它不必在其他任何地方都是const。

char* c = someCharPointerSomewhere;
PointerToConstPointerToChar = PointerToPointerToChar;
*PointerToConstPointerToChar = c // const violation
*PointerToPointerToChar = c // this is fine
// now *PointerToConstPointerToChar will be c as well.

Then why can you not assign to a pointer to a pointer to const ? 那为什么不能分配一个指向const的指针呢? Well, the pointer to const is a different type than a pointer to non const . 好吧,指向const的指针与指向non const的指针是不同的类型。 The implicit conversion we have above does not apply in this case. 我们上面的隐式转换不适用于这种情况。 You could use this pointer to let the pointer it points to point to something, that actually is const . 您可以使用此指针,使其指向的对象实际上是const Then the original pointer would allow to modify the const value indirectly. 然后,原始指针将允许间接修改const值。

const char c = 'c';
PointerToPointerToConstChar = PointerToPointerToChar;
*PointerToPointerToConstChar = c;
**PointerToPointerToChar = 'a'; // const violation!

It is a bit confusing, when you just read the explanations, but take your time and think it through. 当您仅阅读说明但花些时间仔细考虑时,这会有些混乱。 It really is logically consistent that way. 这样在逻辑上确实是一致的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM