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
}
我々が得る:
エラー:代入の左オペランドとしてlvalueが必要です// Dratが再び無効になりました!
したがって、配列の内容は変更できますが、配列のポインタは変更できません。ポインターをユーザーに返すときに、ポインターの状態が一貫していることを確認する場合に適しています。ただし、注意点が1つあります。
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を変更しないでください)、それは非常に適用可能です。ユーザーにフルアクセスを許可して変更する場合は、非constが適しています。
編集:
GetArray()が右の値のオペランドであるために割り当てることができないというokorz001コメントに注目した後、彼のコメントは完全に正しいですが、ポインターへの参照を返す場合にも上記が当てはまります(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()'の割り当て
しかし、2つ目は、その下に潜在的な結果があるにもかかわらず陽気に発生します。
明らかに、「ポインタへの参照を返す必要があるのはなぜですか」という質問が出されますか?問題の元のポインターに直接メモリ(またはデータ)を割り当てる必要がある場合があります(たとえば、独自のmalloc / freeまたはnew / freeフロントエンドを構築する)が、それらのインスタンスでは非const参照です。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'のデクリメント
コメントで示された問題を引き起こしたくないのでなければ、おそらくそれをしたくないので、これは良いことです。const関数でデクリメントを編集すると、次のようになります。
NonConst:A
Const:B
明らかに、Aは 'Data [1]'ですが、NonConstポインターがデクリメント操作を許可したため、 'Data [0]'として扱われています。constを実装すると、別の人が書いているように、潜在的なバグが発生する前にそれをキャッチします。
もう1つの主な考慮事項は、参照が指すものを変更できないという点で、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型と便利なようですが、あなたは、あなたが渡すことができると、それと呼ば変更不可能なポインタを望んでいたグラフィカルアプリケーションの単一スタンスを持っていた場合には考慮していません周り。
その使用法は可変です(意図しないしゃれを除けば)、正しく使用されます。これは、プログラミングを支援するためのボックス内の別のツールです。