因此可以演示 const 指针高度适用的示例。假设您有一个内部带有动态数组的类,并且您希望将用户访问权传递给该数组,但不授予他们更改指针的权限。考虑:
#include <new>
#include <string.h>
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const GetArray(){ return Array; }
};
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
}
产生:
输入数据
放数据
但如果我们试试这个:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
我们得到:
error: lvalue required as left operand of assignment //Drat 再次失败!
很明显我们可以修改数组的内容,但不能修改数组的指针。如果您想确保指针在将指针传递回用户时具有一致的状态,那就太好了。不过有一个问题:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
我们仍然可以删除指针的内存引用,即使我们不能修改指针本身。
因此,如果您希望内存引用始终指向某个东西(IE 永远不会被修改,类似于引用当前的工作方式),那么它非常适用。如果您希望用户拥有完全访问权限并对其进行修改,那么非常量适合您。
编辑:
在注意到 okorz001 注释由于 GetArray() 是一个右值操作数而无法赋值之后,他的注释是完全正确的,但是如果您要返回对指针的引用,上述内容仍然适用(我想我假设 GetArray 指的是引用),例如:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; } //Note & reference operator
char * &GetNonConstArray(){ return Array; } //Note non-const
};
int main()
{
TestA Temp;
Temp.GetArray() = NULL; //Returns error
Temp.GetNonConstArray() = NULL; //Returns no error
}
会在第一次返回导致错误:
错误:分配只读位置 'Temp.TestA::GetArray()'
但第二个会发生,尽管潜在的后果在下面。
很明显,会提出“为什么要返回对指针的引用”的问题?在极少数情况下,您需要将内存(或数据)直接分配给相关的原始指针(例如,构建自己的 malloc/free 或 new/free 前端),但在这些情况下,它是非常量引用.对 const 指针的引用我没有遇到过可以保证它的情况(除非可能作为声明的 const 引用变量而不是返回类型?)。
考虑我们是否有一个接受 const 指针的函数(与不接受的函数相比):
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; }
void ModifyArrayConst(char * const Data)
{
Data[1]; //This is okay, this refers to Data[1]
Data--; //Produces an error. Don't want to Decrement that.
printf("Const: %c\n",Data[1]);
}
void ModifyArrayNonConst(char * Data)
{
Data--; //Argh noo what are you doing?!
Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
printf("NonConst: %c\n",Data[1]);
}
};
int main()
{
TestA Temp;
Temp.ModifyArrayNonConst("ABCD");
Temp.ModifyArrayConst("ABCD");
}
const 中的错误会产生如下消息:
错误:只读参数'Data'递减
这很好,因为我们可能不想这样做,除非我们想引起 cmets 中指出的问题。如果我们在 const 函数中编辑掉减量,会发生以下情况:
非常量:A
常量:B
很明显,即使 A 是“Data[1]”,它也被视为“Data[0]”,因为 NonConst 指针允许减量操作。正如另一个人所写的那样,在实现了 const 后,我们可以在潜在的错误发生之前发现它。
另一个主要考虑因素是 const 指针可以用作伪引用,因为引用指向的东西不能更改(有人想知道,如果这就是它的实现方式)。考虑:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
尝试编译时,产生以下错误:
错误:只读变量“B”的赋值
如果需要对 A 的持续引用,这可能是一件坏事。如果 B = NULL 被注释掉,编译器会很高兴地让我们修改 *B 并因此修改 A。这对于 int 可能看起来没有用,但考虑一下你是否有一个图形应用程序的单一立场,你想要一个不可修改的指针来引用到它,你可以传递。
它的用法是可变的(请原谅无意的双关语),但如果使用正确,它是盒子里另一个辅助编程的工具。