constポインターのポイントは何ですか?


149

私はconst値へのポインターについて話しているのではなく、constポインター自体について話している。

私は非常に基本的なものを超えてCとC ++を学んでいて、今日まで、ポインタが値によって関数に渡されることに気づきました。これは理にかなっています。つまり、関数内では、呼び出し元からの元のポインターに影響を与えることなく、コピーしたポインターを他の値にポイントできます。

それで、関数ヘッダーがあることの意味は何ですか?

void foo(int* const ptr);

このような関数の内部では、ptrを他のものにポイントすることはできません。これはconstであり、変更したくないためですが、次のような関数です。

void foo(int* ptr);

同様に仕事をします!ポインタはとにかくコピーされ、コピーを変更しても呼び出し元のポインタは影響を受けないためです。それでは、constの利点は何ですか?


29
コンパイル時に、ポインターが他のものを指すように変更できないこと、および変更すべきでないことを保証したい場合はどうでしょうか?
プラチナAzure

25
constパラメータとまったく同じポイント。
David Heffernan

2
@PlatinumAzure、私はプログラミングの数年の経験を持っていますが、それでも私のソフトウェア実践は欠けています。コンパイラに自分の論理エラーを指摘させる必要性を感じたことがないので、この質問をしてよかったです。質問を送信したときの私の最初の反応は、「ポインターが変更された場合、どうして気にする必要があるのですか?呼び出し元には影響しません」でした。すべての回答を読むまで、気をつけるべきだと理解していました。変更しようとすると、コーディングロジックが間違っている(またはアスタリスクがないなどのタイプミスがあった)ため、コンパイラーが認識していないと気付かなかった可能性があります。 t教えてください。
R.ルイス。

3
@ R.Ruiz。間違いなく、私たちの最も経験豊富な人でさえ、正確さをさらに保証することで対応できます。ソフトウェアエンジニアリングは、多少の余裕が許容されるエンジニアリングの形式であるため(ランダムなHTTP 502、遅い接続、ロードに失敗することのある偶発的なイメージは異常な場合ではありませんが、飛行機でのエンジンの失敗は許容できず、おそらく深刻です)、時には人々は過度の速攻でプログラムします。単体テストの記述を正当化する同じ議論は、- const正確性の保証の使用を説明します。コードが間違いなく正しいことを確信させるだけです。
プラチナAzure

回答:


207

const は、非常に重要なC ++の概念を追求するために使用するツールです。

コンパイラにあなたの意図することを強制することで、実行時ではなくコンパイル時にバグを見つけます。

機能は変更されませんが、const意図しないことを行っている場合、追加するとコンパイラエラーが発生します。次のタイプミスを想像してみてください。

void foo(int* ptr)
{
    ptr = 0;// oops, I meant *ptr = 0
}

を使用int* constすると、値をに変更するため、コンパイラエラーが発生しptrます。構文を介して制限を追加することは、一般的に良いことです。あまり遠慮しないでください。あなたが与えた例は、ほとんどの人がを使用することに煩わされないケースconstです。


8
ありがとう、これは私を納得させる答えです。コンパイラーが独自の割り当てエラーについて警告するように、constを配置します。これはポインタに関するよくある間違いであるため、この例はこの概念を説明するのに最適です。あなたより!
R.ルイス。

25
「コンパイラがあなたを助けるのを助ける」は、私が通常これを唱えているマントラです。
フレキソ

1
+1が、ここではそれがargueableで興味深いケースです:stackoverflow.com/questions/6305906/...
レドワルド

3
したがって、「クラスの外で変数を使用できないのに、なぜ変数をプライベートにするのか」と同じ答えになります。
Lee Louviere、2012年

これは少し外れたトピックかもしれませんが、このconstポインタはメモリのどこにありますか?私はすべてのconstがメモリのグローバル部分にあることを知っていますが、func varとして渡されるconstについては100%確信がありません。これがトピックから外れている場合は、ありがとう、ごめんなさい
トーマー

77

引数だけ を使用constすることにしました。これにより、より多くのコンパイラチェックが可能になります。関数内で引数の値を誤って再割り当てすると、コンパイラが噛み付いてしまいます。

私はめったに変数を再利用しません。新しい値を保持するために新しい変数を作成する方がきれいなので、基本的にすべての変数宣言はconstconstコードが機能しないループ変数などの場合を除いて)です。

これは関数の定義でのみ意味があることに注意してください。ユーザーに表示される宣言には属していません。そして、ユーザーはconst関数内のパラメーターに使用するかどうかを気にしません。

例:

// foo.h
int frob(int x);
// foo.cpp
int frob(int const x) {
   MyConfigType const config = get_the_config();
   return x * config.scaling;
}

引数とローカル変数の両方がどのようになっているかに注意してくださいconst。どちらも必要でありませんが、少しだけ大きい関数を使用することで、間違いを何度も繰り返すことがなくなりました。


17
+1別のconst熱狂的な狂信者から。しかし、私はコンパイラーが私に吠えるのを好みます。私はあまりにも多くのエラーを犯し、彼らが噛むのをひどく苦しむでしょう。
sbi

2
+1、「const正当な理由がない限り」の戦略を強くお勧めします。ただし、いくつかの良い例外があります。たとえば、コピーとスワップ
Flexo

2
新しい言語を設計している場合、宣言されたオブジェクトはデフォルトで読み取り専用( "const")になります。オブジェクトを書き込み可能にするには、特別な構文、おそらく「var」キーワードが必要です。
キース・トンプソン

@キース私は「もちろん」と言いたくなります。この時点で他のすべては愚かです。しかし残念ながら、ほとんどの言語デザイナーは私たちに反対しているようです…実際、私はすでに同じくらい投稿しました(今削除された質問、「あなたの最も物議を醸しているプログラミングの意見は?」)。
Konrad Rudolph

1
@KubaOber悲観化なんて全然分かりません。関数の本体内で渡されたものを後で変更する必要があることがわかった場合constは、引数からを削除し、できれば理由をコメントしてください。そのほんの少しの余分な作業はconst、デフォルトですべての引数を非としてマーク付けし、作成するすべての潜在的なエラーに自分自身を開放することを正当化しません。
underscore_d 2017年

20

あなたの質問はより一般的なものに触れています:関数の引数はconstでなければなりませんか?

値の引数の一貫性(ポインタのような)は実装の詳細であり、関数宣言の一部ではありませ。つまり、関数は常に次のようになります。

void foo(T);

関数スコープの引数変数を可変で使用するか、定数で使用するかは、関数の実装者次第です。

// implementation 1
void foo(T const x)
{
  // I won't touch x
  T y = x;
  // ...
}

// implementation 2
void foo(T x)
{
  // l33t coding skillz
  while (*x-- = zap()) { /* ... */ }
}

したがって、単純なルールに従ってconst宣言(ヘッダー)を絶対に入れず、変数を変更したくない、または変更する必要がない場合は定義(実装)に入れます。


5
私はこれに同意します-しかし、宣言と定義を異なるものにするという考えには多少不快です。以外のものについてconstは、宣言と定義(のプロトタイプ部分)は一般に同一になります。
Keith Thompson

@KeithThompson:まあ、したくないのならそれをする必要はありません。const宣言を入れないでください。実装に修飾子を追加するかどうかは、完全にあなた次第です。
Kerrek SB、2011

1
私が言ったように、私constは宣言をするが定義は意味がないことに同意します。これは、宣言と定義を同一でなくすることが理にかなっている唯一のケースであることは、言語のグリッチのように感じられます。(もちろん、Cの唯一の不具合ではありません。)
キース・トンプソン、

16

最上位のconst修飾子は宣言では破棄されるため、質問の宣言はまったく同じ関数を宣言します。一方、定義(実装)では、ポインターをconstとしてマークした場合、関数の本体内で変更されていないことをコンパイラーが確認します。


知らなかった。したがって、void foo(int * const ptr)をvoid foo(int * t ptr)でオーバーロードしようとすると、コンパイラエラーが発生します。ありがとう!
R.ルイス。

@ R.Ruiz。減速がvoid foo(int * t ptr)であり、定義がvoid foo(int * const ptr)である場合、コンパイラエラーは発生しません。
Trevor Hickey

1
@TrevorHickey彼らはそうします...しかし、彼らが考える理由ではありません。int* t ptr構文エラーです。それがなければ、2つはオーバーロードの目的で同一です。
underscore_d 2017年

14

あなたが正しい、発信者にとってそれは全く違いがありません。しかし、関数の作成者にとっては、「大丈夫、私はこのことを間違った点に向けないようにする必要がある」というセーフティネットにすることができます。あまり役に立ちませんが、役に立たないわけでもありません。

基本的にはint const the_answer = 42、プログラムにを含めるのと同じです。


1
彼らがそれを指す場所はどういう意味ですか、それはスタックに割り当てられたポインターですか?関数はそれを台無しにすることはできません。ポインターツーポインターを扱う場合は、読み取り専用ポインターを使用する方がはるかに理にかなっています。int constと同じではありません!その誤解を招く発言のために、私はこれに反対票を投じます。const intint constは同等ですが、const int*とにint* constは2つの異なる意味があります!
ランディン

1
@lundin関数が大きく、他のものが含まれているとしましょう。誤って、(関数のスタック上の)他の何かを指すようにする場合があります。これは発信者には問題ありませんが、確実に着信者に発生する可能性があります。私の発言には誤解を招くようなものはありません。「関数の作成者にとって、これはセーフティネットになる可能性があります」。
cnicutar

1
@Lundin int const一部について; 私はしばらくタイプをconst(不自然に聞こえます)の前に置き、その違いを認識しています。この記事は役に立つかもしれません。私自身、このスタイルに切り替える理由は少し異なりました。
cnicutar

1
はい。誰か他の人があなたと私がこの投稿を読んでいる場合に備えて、私は自分自身の長い間返事を書きました。int constが悪いスタイルでconst intが良いスタイルである理由も含めました。
Lundin、

ランディン、私も読んでいます!私はconst intがより良いスタイルであることに同意します。@ cnicutar、Lundinへの最初の応答は、私がこの質問を送信したときに探していたものです。したがって、問題は呼び出し元にはありませんが(私は無邪気に考えました)、constは呼び出し先の保証です。私はこの考えが好きです、ありがとう。
R.ルイス。

14

constキーワードにはたくさんありますが、かなり複雑です。一般に、プログラムに多くのconstを追加することは、プログラミングのよい習慣と見なされ、「constの正確さ」をWebで検索すると、それに関する多くの情報が見つかります。

constキーワードは、いわゆる「型修飾子」であり、その他はvolatileand restrictです。少なくともvolatileはconstと同じ(混乱する)ルールに従います。


まず、constキーワードには2つの目的があります。最も明白な方法は、データ(およびポインタ)を読み取り専用にすることで、意図的または偶発的な誤用から保護することです。const変数を変更しようとする試みは、コンパイル時にコンパイラーによって検出されます。

しかし、読み取り専用メモリを備えたシステムには別の目的もあります。つまり、特定の変数がそのようなメモリ内に割り当てられるようにすることです。たとえば、EEPROMやフラッシュなどです。これらは、不揮発性メモリ、NVMとして知られています。もちろん、NVMで割り当てられた変数は、const変数のすべてのルールに従います。

constキーワードを使用するには、いくつかの異なる方法があります。

定数変数を宣言します。

これは次のいずれかで行うことができます

const int X=1; or
int const X=1;

これら2つの形式は完全に同等です。後者のスタイルは悪いスタイルと見なされ、使用しないでください。

2行目が不適切なスタイルと見なされる理由は、staticやexternなどの「ストレージクラス指定子」も実際の型のに宣言できるint staticためなどです。 C委員会(ISO 9899 N1539ドラフト、6.11.5)。したがって、一貫性を保つために、型修飾子をそのように記述することはできません。とにかく読者を混乱させる以外の目的はありません。

定数変数へのポインターを宣言します。

const int* ptr = &X;

つまり、「X」の内容は変更できません。これは、主に「const correctness」の関数パラメーターの一部として、このようにポインターを宣言する通常の方法です。「X」は実際にはconstとして宣言する必要がないため、任意の変数にすることができます。つまり、変数を常にconstに「アップグレード」できます。技術的には、Cは明示的な型キャストによってconstからプレーン変数にダウングレードすることもできますが、そうすることは悪いプログラミングと見なされ、コンパイラーは通常それに対して警告を出します。

定数ポインターを宣言する

int* const ptr = &X;

これは、ポインタ自体が一定であることを意味します。ポインターの向きを変更できますが、ポインター自体は変更できません。これには多くの用途はありませんが、関数へのパラメーターとして渡されている間、ポインターが指す(ポインターからポインター)のアドレスが変更されないようにするなど、いくつかの用途があります。次のように読みづらいものを書く必要があります:

void func (int*const* ptrptr)

多くのCプログラマーがconstと*をそこに正しく入力できるとは思えません。私は知っているできません-私はGCCに確認しなければなりませんでした。これが、ポインターツーポインターの構文がプログラミングの練習として考えられているにもかかわらず、めったに見られない理由だと思います。

定数ポインターを使用して、ポインター変数自体が読み取り専用メモリで宣言されていることを確認することもできます。たとえば、ある種のポインターベースのルックアップテーブルを宣言して、NVMに割り当てることができます。

そしてもちろん、他の回答で示されているように、定数ポインターを使用して「constの正確さ」を強制することもできます。

定数データへの定数ポインターを宣言する

const int* const ptr=&X;

これは、上記で説明した2つのポインタタイプを組み合わせたもので、それらのすべての属性が両方とも含まれています。

読み取り専用メンバー関数を宣言する(C ++)

これはC ++でタグ付けされているので、クラスのメンバー関数をconstとして宣言できることにも触れておきます。これは、関数が呼び出されたときにクラスの他のメンバーを変更することが許可されていないことを意味します。これにより、クラスのプログラマーが偶発的なエラーを防ぐだけでなく、メンバー関数の呼び出し元に混乱を招くこともありません。それを呼び出すことによってアップ。構文は次のとおりです。

void MyClass::func (void) const;

8

...今日、ポインタが値によって関数に渡されることに気づきました。これは理にかなっています。

(imo)それはデフォルトとして本当に意味がありません。より賢明なデフォルトは、再割り当て不可能なポインタ(int* const arg)として渡すことです。つまり、引数として渡されるポインターが暗黙的にconstとして宣言されていることを優先しました。

それでは、constの利点は何ですか?

利点は、引数が指すアドレスを変更するときにそれが十分に簡単で、時には不明確になることです。そのため、constがやや簡単ではないときにバグが発生する可能性があります。アドレスの変更は非定型です。アドレスを変更する場合は、ローカル変数を作成する方が明確です。同様に、生のポインタ操作はバグを導入する簡単な方法です。

したがって、引数が指すアドレスを変更したい場合は、不変のアドレスを渡してコピーを作成すること(これらの非定型の場合)がより明確になります。

void func(int* const arg) {
    int* a(arg);
    ...
    *a++ = value;
}

そのローカルを追加することは事実上無料であり、読みやすさを向上させながら、エラーの可能性を減らします。

より高いレベルで:引数を配列として操作している場合、通常、引数をコンテナー/コレクションとして宣言する方がクライアントにとってより明確でエラーが発生しにくくなります。

一般に、値、引数、アドレスにconstを追加することは、コンパイラーが喜んで実行する副作用を常に認識しているわけではないため、良い考えです。したがって、他のいくつかのケースで使用されるのと同じくらいconstと同じくらい便利です(たとえば、質問は「なぜconst値を宣言する必要があるのか​​?」に似ています)。幸いにも、再割り当てできない参照があります。


4
+1がデフォルトです。C ++は、ほとんどの言語と同様に、間違った方法を持っています。constキーワードを持つのではなく、キーワードを持つべきですmutable(まあ、それはありますが、セマンティクスが間違っています)。
Konrad Rudolph

2
デフォルトとしてconstを持つ興味深いアイデア。ご回答有難うございます!
R.ルイス。

6

メモリマップされたデバイスがある組み込みシステムまたはデバイスドライバープログラミングを行う場合、両方の形式の 'const'がよく使用されます。1つはポインターが再割り当てされないようにするためです(固定ハードウェアアドレスを指すため)。それが指すレジスタは読み取り専用のハードウェアレジスタであり、別のconstは実行時ではなくコンパイル時に多くのエラーを検出します。

読み取り専用の16ビットペリフェラルチップレジスタは次のようになります。

static const unsigned short *const peripheral = (unsigned short *)0xfe0000UL;

その後、アセンブリ言語に頼ることなく、ハードウェアレジスタを簡単に読み取ることができます。

input_word = *peripheral;


5

int iVal = 10; int * const ipPtr =&iVal;

通常のconst変数と同様に、constポインターは宣言時に値に初期化する必要があり、その値は変更できません。

つまり、constポインターは常に同じ値を指します。上記の場合、ipPtrは常にiValのアドレスを指します。ただし、ポイントされている値はまだconstではないため、ポインターを逆参照することで、ポイントされている値を変更できます。

* ipPtr = 6; // pnPtrが非const intを指すので許可


5

他のタイプ(ポインターだけでなく)についても同じ質問をすることができます。

/* Why is n const? */
const char *expand(const int n) {
    if (n == 1) return "one";
    if (n == 2) return "two";
    if (n == 3) return "three";
    return "many";
}

笑、あなたは正しいです。ポインタは特別だと思ったので、最初に思いついたのはポインタですが、値によって渡される他の変数と同じです。
R.ルイス。

5

あなたの質問は、関数への単なるconstポインタパラメータではなく、なぜconstとして変数を定義するかについての詳細です。ここでは、関数へのパラメーター、メンバー変数、またはローカル変数の場合、変数を定数として定義する場合と同じ規則が適用されます。

あなたの特定のケースでは、機能的にはローカル変数をconstとして宣言する他の多くの場合のように違いはありませんが、この変数を変更できないという制限を課します。


あなたのコメントはあなたが正しいので私の質問がいかに無駄であるかを理解させます:それはconstとして他のパラメーターを持つことと同じことです。それは役に立たないように見えるかもしれませんが、プログラマーがこの制限を持ち、バグを回避するのを助けるためにあります
R. Ruiz。

4

関数にconstポインタを渡しても、値によって渡されるため、ほとんど意味がありません。これは、一般的な言語設計で許可されているものの1つにすぎません。それが意味をなさないという理由だけでそれを禁止することは、言語仕様を作るだけです。大きい。

関数内にいる場合はもちろん別のケースです。ポインターが指すものを変更できないポインターを持つことは、コードをより明確にするアサーションです。


4

このポインタが変更できないことを知っていれば、コンパイラが関数内でより積極的な最適化を実行できるという利点があると思います。

それはまた避けます。このポインターを非constポインター参照を受け入れるサブ関数に渡す(したがって、ポインターをのように変更する可能性がありますvoid f(int *&p))が、この場合、有用性がいくらか制限されることに同意します。


最適化の場合は+1。少なくとも本はそれが本当だと言う。私が望むのは、それらの最適化が何であるかを正確に理解することです
R. Ruiz。

4

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型と便利なようですが、あなたは、あなたが渡すことができると、それと呼ば変更不可能なポインタを望んでいたグラフィカルアプリケーションの単一スタンスを持っていた場合には考慮していません周り。

その使用法は可変です(意図しないしゃれを除けば)、正しく使用されます。これは、プログラミングを支援するためのボックス内の別のツールです。


2
Temp.GetArray() = NULLTemp.GetArray()は右辺値なので失敗します。const修飾されているためではありません。さらに、const-qualifierはすべての戻り値の型から取り除かれていると思います。
オスカーコルツ

@ okorz001:テスト後、あなたは確かに正しいです。ただし、ポインタ自体への参照を返す場合は、上記が当てはまります。それに応じて投稿を編集します。
SSight3、2011年

3

ポインターをconstにしたくない場合は、ポインターについて特別なことは何もありません。クラスメンバーの定int数値を持つことができるのと同じように、同様の理由で定数ポインターを持つこともできます。ポイントされているものを誰も変更しないようにしたい場合。C ++リファレンスはこれに多少対処していますが、ポインターの動作はCから継承されています。


3

これにより、コードが関数本体内のポインターをインクリメントまたはデクリメントするのを防ぐことができると思います。


3

-
(1)定数変数の宣言のような変数を宣言するタイプ
DataType const varibleName;

 int const x;
    x=4; //you can assign its value only One time
(2)定数変数へのポインタを宣言する
const dataType* PointerVaribleName=&X;
 const int* ptr = &X;
     //Here pointer variable refer contents of 'X' that is const Such that its cannot be modified
dataType* const PointerVaribleName=&X;
 int* const ptr = &X;
     //Here pointer variable itself is constant  Such that value of 'X'  can be modified But pointer can't be modified


実際の値を変更したくない場合は、ポインタ変数をconstとして関数への引数として提供します
Pyadav
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.