1625

const int*私はいつも、、、const int * constそしてint const *正しく使用する方法を台無しにします。できることとできないことを定義する一連のルールはありますか?

割り当て、関数への受け渡しなどに関して、すべてのすべきこととすべきでないことを知りたいです。

4

21 に答える 21

2595

逆方向に読んでください(時計回り/スパイラルルールによって駆動されます):

  • int*--intへのポインタ
  • int const *--constintへのポインタ
  • int * const--intへのconstポインタ
  • int const * const--constintへのconstポインタ

これで、最初constはタイプのいずれかの側に配置できるため、次のようになります。

  • const int *==int const *
  • const int * const==int const * const

あなたが本当に夢中になりたいなら、あなたはこのようなことをすることができます:

  • int **--intへのポインタへのポインタ
  • int ** const-intへのポインタへのconstポインタ
  • int * const *--constへのポインタintへのポインタ
  • int const **-constintへのポインタへのポインタ
  • int * const * const-intへのconstポインタへのconstポインタ
  • ..。

そして、私たちが:の意味を明確にすることを確認するためにconst

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.



int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

foo定数整数への変数ポインタです。これにより、ポイントするものを変更できますが、ポイントする値は変更できません。ほとんどの場合、これは、へのポインタがあるCスタイルの文字列で見られますconst char。指す文字列を変更することはできますが、これらの文字列の内容を変更することはできません。これは、文字列自体がプログラムのデータセグメントにあり、変更してはならない場合に重要です。

bar変更可能な値への定数または固定ポインタです。これは、余分な構文糖衣がないリファレンスのようなものです。T* constこの事実のため、通常、ポインターを許可する必要がない限り、ポインターを使用する参照を使用しNULLます。

于 2009-07-17T13:29:58.390 に答える
462

時計回り/スパイラルルールについて知らない人のために:変数の名前から始めて、時計回りに移動し(この場合は後方に移動します)、次のポインターに移動するか、と入力します。式が終了するまで繰り返します。

これがデモです:

intへのポインタ

intconstへのconstポインタ

intconstへのポインタ

constintへのポインタ

intへのconstポインタ

于 2015-07-10T02:15:22.377 に答える
172

ここですべてがすでに答えられていると思いますが、私はあなたがtypedefsに注意する必要があることを付け加えたいと思います!それらは単なるテキスト置換ではありません。

例えば:

typedef char *ASTRING;
const ASTRING astring;

のタイプastringchar * const、ではありませんconst char *constこれが、私が常にタイプの右側に配置する傾向があり、最初は決して配置しない理由の1つです。

于 2009-07-17T13:39:47.317 に答える
67

ほとんどの人が指摘したように:

const X* pX* const pとの違いは何const X* const pですか?

ポインタ宣言を右から左に読む必要があります。

  • const X* p「pはconstであるXを指している」という意味です。Xオブジェクトはpを介して変更できません。

  • X* const p「pは非constであるXへのconstポインタです」を意味します。ポインタp自体を変更することはできませんが、pを介してXオブジェクトを変更することはできます。

  • const X* const p「pはconstであるXへのconstポインタ」を意味します。ポインタp自体を変更することも、pを介してXオブジェクトを変更することもできません。

于 2009-07-17T13:36:54.650 に答える
52
  1. 一定の参照:

    定数である変数(ここではint)への参照。参照は実際の値よりもサイズが小さいため、主に変数を参照として渡しますが、副作用があり、それは実際の変数のエイリアスのようなものであるためです。エイリアスへのフルアクセスによって誤ってメイン変数を変更する可能性があるため、この副作用を防ぐために一定にしています。

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
  2. 定数ポインタ

    定数ポインタが変数を指すと、他の変数を指すことはできません。

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
  3. 定数へのポインタ

    指す変数の値を変更できないポインターは、定数へのポインターと呼ばれます。

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
  4. 定数への定数ポインタ

    定数への定数ポインターは、それが指しているアドレスを変更することも、そのアドレスに保持されている値を変更することもできないポインターです。

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    
于 2014-05-17T20:21:03.257 に答える
23

原則として、constキーワードはその直前に適用されます。例外として、開始constは次のものに適用されます。

  • const int*「定数intへのポインタ」と同じでint const*あり、それを意味します。
  • const int* constは「定数intへの定数ポインタ」と同じでint const* constあり、それを意味します。

編集: すべきこととすべきでないことについて、この答えが十分でない場合、あなたはあなたが望むものについてより正確にできますか?

于 2009-07-17T13:30:06.860 に答える
22

この質問は、私の質問で述べた方法がタイプIDの後にconstである理由を正確に示していますか?

要するに、ルールを覚える最も簡単な方法は、「c​​onst」が適用されるものの後に続くということです。したがって、あなたの質問では、「int const *」はintが定数であることを意味し、「int*const」はポインタが定数であることを意味します。

誰かがそれを一番前に置くことにした場合(例: "const int *")、その場合の特別な例外として、それはその後のものに適用されます。

多くの人は、見栄えが良いと思うので、その特別な例外を使用するのが好きです。それは例外であり、物事を混乱させるので、私はそれが嫌いです。

于 2009-07-17T13:52:23.040 に答える
19

の簡単な使用const

最も簡単な使用法は、名前付き定数を宣言することです。これを行うには、定数を変数であるかのように宣言しますが、そのconst前に追加します。もちろん、値を変更するため、後で値を設定することはできないため、コンストラクターですぐに初期化する必要があります。例えば:

const int Constant1=96; 

Constant1は、想像を絶するほどと呼ばれる、値96の整数定数を作成します。

このような定数は、プログラムで使用されるパラメーターに役立ちますが、プログラムのコンパイル後に変更する必要はありません。これは、Cプリプロセッサコマンドよりもプログラマーにとって利点があり#define、メインコンパイラに到達する前にプリプロセッサによってプログラムテキストに置き換えられるだけでなく、コンパイラ自体によって理解および使用されるため、エラーメッセージがはるかに役立ちます。

constポインタでも機能しますが、ポインタまたはポインタが指すものが一定であるか、あるいはその両方であるかを判断する場所に注意する必要があります。例えば:

const int * Constant2 

Constant2それが定数整数への変数ポインタであることを宣言し、次のようにします。

int const * Constant2

は同じことを行う代替構文ですが、

int * const Constant3

Constant3それが可変整数への定数ポインタであることを宣言し、

int const * const Constant4

Constant4それが定数整数への定数ポインタであることを宣言します。基本的に、「const」はそのすぐ左にあるものすべてに適用されます(そこに何もない場合を除いて、そのすぐ右にあるものすべてに適用されます)。

参照:http ://duramecho.com/ComputerInformation/WhyHowCppConst.html

于 2009-07-17T13:31:45.407 に答える
12

シンプルですが注意が必要です。const修飾子は任意のデータ型(、、、intなど)charに適用できることに注意してくださいfloat

以下の例を見てみましょう。


const int *p==>*pは読み取り専用です[p定数整数へのポインタです]

int const *p==>*pは読み取り専用です[p定数整数へのポインタです]


int *p const==>間違ったステートメント。コンパイラは構文エラーをスローします。

int *const p==>pは読み取り専用です[p整数への定数ポインタです]。ここでのポインタpは読み取り専用であるため、宣言と定義は同じ場所にある必要があります。


const int *p const ==>間違ったステートメント。コンパイラは構文エラーをスローします。

const int const *p ==>*pは読み取り専用です

const int *const p ==>*pそしてp読み取り専用です[p定数整数への定数ポインタです]。ここでのポインタpは読み取り専用であるため、宣言と定義は同じ場所にある必要があります。


int const *p const ==>間違ったステートメント。コンパイラは構文エラーをスローします。

int const int *p ==>間違ったステートメント。コンパイラは構文エラーをスローします。

int const const *p ==>*pは読み取り専用であり、int const *p

int const *const p ==>*pそしてp読み取り専用です[p定数整数への定数ポインタです]。ここでのポインタpは読み取り専用であるため、宣言と定義は同じ場所にある必要があります。

于 2015-01-04T13:10:45.500 に答える
11

C++の第一人者であるScottMeyersがこのに出くわすまで、私はあなたと同じ疑問を抱いていました。彼が使用について詳細に話しているこの本の3番目の項目を参照してくださいconst

このアドバイスに従ってください

  1. アスタリスクの左側に単語constが表示されている場合、ポイントされているのは一定です
  2. 単語constがアスタリスクの右側に表示されている場合、ポインター自体は一定です
  3. const両側に表示される場合、両方が一定です
于 2015-03-21T13:56:12.870 に答える
8

CおよびC++宣言構文は、元の設計者によって、失敗した実験として繰り返し説明されてきました。

代わりに、タイプに「pointerto」という名前を付けましょうType。私はそれを呼びますPtr_

template< class Type >
using Ptr_ = Type*;

Ptr_<char>はへのポインタcharです。

Ptr_<const char>へのポインタconst charです。

そしてconst Ptr_<const char>、へのconstポインタconst charです。

于 2016-01-06T00:12:59.747 に答える
7

私にとって、constつまり、それが左または右に表示されるか、左と右の両方に表示されるかという位置は*、実際の意味を理解するのに役立ちます。

  1. constの左側のA*は、ポインタが指すオブジェクトがオブジェクトであることを示しconstます。

  2. constの右側のA*は、ポインタがポインタであることを示しconstます。

次の表は、スタンフォードCS106L標準C++プログラミングラボコースリーダーから抜粋したものです。

ここに画像の説明を入力してください

于 2019-02-04T07:48:16.050 に答える
6

C++の定数の正確さを取り巻く他の多くの微妙な点があります。ここでの質問は単にCに関するものだと思いますが、タグがC ++であるため、関連する例をいくつか示します。

  • 文字列のような大きな引数を渡すことがよくTYPE const &あります。これにより、オブジェクトが変更またはコピーされるのを防ぎます。例 :

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    しかしTYPE & const、参照は常に定数であるため、意味がありません。

  • クラスを変更しないクラスメソッドには常にラベルを付ける必要があります。そうしないと、参照constからメソッドを呼び出すことができません。TYPE const &例 :

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • 戻り値とメソッドの両方がconstである必要がある一般的な状況があります。例 :

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    実際、constメソッドは、非constへの参照として内部クラスデータを返さないようにする必要があります。

  • その結果、多くの場合、constオーバーロードを使用してconstメソッドとnon-constメソッドの両方を作成する必要があります。たとえば、を定義する場合はT const& operator[] (unsigned i) const;、次の式で指定された非定数バージョンも必要になる可能性があります。

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

Afaik、Cにはconst関数はなく、非メンバー関数自体をC ++でconstにすることはできません。また、constメソッドには副作用がある可能性があり、コンパイラーはconst関数を使用して重複する関数呼び出しを回避できません。実際、単純なint const &参照でさえ、それが参照する値が他の場所で変更されるのを目撃する可能性があります。

于 2011-09-13T10:50:54.940 に答える
6

簡単に覚えるには:

constが*の前にある場合、値は定数です。

constが*の後にある場合、アドレスは一定です。

constが*の前後の両方で使用可能な場合、値とアドレスの両方が一定です。

例えば

  1. int * const var; //ここでアドレスは定数です。

  2. int const * var; //ここで値は定数です。

  3. int const * const var; //値とアドレスの両方が一定です。

于 2021-05-01T18:59:49.533 に答える
5

いずれかの側にintがあるconstは、定数intへのポインターを作成します。

const int *ptr=&i;

また:

int const *ptr=&i;

constafterはintへの定数ポインタを*作成します:

int *const ptr=&i;

この場合、これらはすべて定数整数へのポインターですが、これらはいずれも定数ポインターではありません。

 const int *ptr1=&i, *ptr2=&j;

この場合、すべてが定数整数へのポインターであり、ptr2は定数整数への定数ポインターです。ただし、ptr1は定数ポインタではありません。

int const *ptr1=&i, *const ptr2=&j;
于 2018-09-23T08:44:06.513 に答える
4
  • の左側にあるconst場合、それは値を参照します(それがであるかどうかは関係ありません)*const intint const
  • の右側にある場合constは、ポインタ自体を指します*
  • それは同時に両方である可能性があります

重要なポイント:const int *p あなたが参照している値が一定であるという意味ではありません!! これは、そのポインタを介して変更できないことを意味します(つまり、$ * p = ... `を割り当てることはできません)。値自体は他の方法で変更される場合があります。例えば

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error 

これは、関数が渡された引数を誤って変更できないことを保証するために、主に関数のシグネチャで使用されることを意図しています。

于 2019-07-31T17:55:45.620 に答える
3

これは主に2行目(ベストプラクティス、割り当て、関数パラメーターなど)に対応しています。

一般診療。あなたができるすべてを作るようにしconstてください。または、別の言い方をすれば、最初にすべてを作成してから、プログラムを機能させるために必要なconst最小限のセットを正確に削除します。constこれは、const-correctnessを達成する上で大きな助けとなり、人々が変更するはずのないものに割り当てようとしたときに微妙なバグが発生しないようにするのに役立ちます。

疫病のようにconst_cast<>は避けてください。正当なユースケースは1つか2つありますが、それらはごくわずかであり、その間にあります。オブジェクトを変更しようとしている場合は、最初のペースconstでそれを宣言した人を見つけてconst、何が起こるべきかについて合意に達するために彼らと問題について話し合う方がはるかに良いでしょう。

これは非常にきちんと割り当てにつながります。非定数の場合にのみ、何かに割り当てることができます。constであるものに割り当てる場合は、上記を参照してください。int const *foo;宣言にint * const bar;はさまざまなことが含まれていることを忘れないでください。constここでの他の回答はその問題を立派にカバーしているので、ここでは取り上げません。

関数パラメーター:

値渡し:たとえばvoid func(int param)、呼び出し元のサイトでどちらの方法でもかまいません。関数をとして宣言するユースケースがありますがvoid func(int const param)、呼び出し中に関数が渡す値は変更できないという点で、呼び出し元には影響せず、関数自体にのみ影響するという議論をすることができます。

参照渡し:たとえばvoid func(int &param)、今では違いが生じます。宣言されたばかりのfuncように、変更が許可されてparamおり、呼び出し元のサイトはその結果に対処する準備ができている必要があります。宣言を変更して契約を変更し、変更できないことvoid func(int const &param)を保証します。つまり、渡されたものが返されるものです。他の人が指摘しているように、これは変更したくない大きなオブジェクトを安価に渡すのに非常に便利です。参照を渡すことは、大きなオブジェクトを値で渡すよりもはるかに安価です。funcparam

ポインタを渡す:egvoid func(int *param)void func(int const *param)これら2つは、対応する参照とほぼ同義ですが、nullptr他の契約上の保証でinfuncを受け取らないことが保証されていない限り、呼び出された関数がチェックする必要があるという警告があります。nullptrparam

そのトピックに関する意見記事。このような場合に正しさを証明することは非常に困難であり、間違いを犯すのは非常に簡単です。したがって、チャンスを逃さず、常にポインタパラメータをチェックしてくださいnullptr。あなたは自分自身の痛みと苦しみを救い、長期的にはバグを見つけるのが難しいでしょう。そして、チェックのコストに関しては、それはかなり安いです、そしてコンパイラーに組み込まれた静的分析がそれを管理することができる場合、オプティマイザーはとにかくそれを排除します。MSVCの場合はリンク時コード生成、GCCの場合はWOPR(私は思う)をオンにすると、プログラム全体で、つまりソースコードモジュールの境界を越える関数呼び出しでも使用できるようになります。

結局のところ、上記のすべては、常にポインタへの参照を好むという非常に堅実なケースになります。彼らはすべてのラウンドでより安全です。

于 2018-03-15T07:59:23.037 に答える
2

他の説明に従ったCの完全性のために、C++についてはわかりません。

  • pp-ポインタへのポインタ
  • p-ポインタ
  • データ-例で指摘されていることx
  • 太字-読み取り専用変数

ポインタ

  • pデータ-int *p;
  • pデータ-int const *p;
  • pデータ-int * const p;
  • p データ-int const * const p;

ポインタへのポインタ

  1. pppデータ-int **pp;
  2. pppデータ-int ** const pp;
  3. pppデータ-int * const *pp;
  4. pppデータ-int const **pp;
  5. ppp データ-int * const * const pp;
  6. pppデータ- _int const ** const pp;
  7. pppデータ- _ int const * const *pp;
  8. ppp データ- _ int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

Nレベルの間接参照

続けてください、しかし人類があなたを破門するかもしれません。

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;

printf("%d \n", ****pppp);
于 2019-02-17T16:30:04.760 に答える
1
  1. const int*-定数intオブジェクトへのポインタ。

ポインタの値を変更できます。オブジェクトの値を変更することはできませんint。ポインタが指します。


  1. const int * const-定数intオブジェクトへの定数ポインタ。

intポインタの値やポインタが指すオブジェクトの値を変更することはできません。


  1. int const *-定数intオブジェクトへのポインタ。

このステートメントは1と同等です。-ポインターの値を変更することはできますが、ポインターが指すオブジェクトconst int*の値を変更することはできません。int


実際には、4番目のオプションがあります。

  1. int * constint-オブジェクトへの定数ポインタ。

ポインタが指すオブジェクトの値を変更することはできますが、ポインタ自体の値を変更することはできません。ポインタは常に同じintオブジェクトを指しますが、このオブジェクトのこの値はint変更できます。


特定のタイプのCまたはC++構造を判別する場合は、DavidAndersonによって作成された時計回り/スパイラルルールを使用できます。しかし、ロス・J・アンダーソンによって作成されたアンダーソンの規則と混同しないでください。これはまったく異なるものです。

于 2020-02-07T14:30:04.290 に答える
1

単純なニーモニック:

typeポインタ<-- *>ポインタname


私は「の間接参照は」int *iを宣言することと考えるのが好きです。この意味で、は「のderefは」を意味し、「のderefは」を意味します。iintconst int *iiconst intint *const iconst iint

int const *i(このように考えることの1つの危険は、人々が嫌い/禁止するかもしれない宣言のスタイルを支持することにつながるかもしれないということです)

于 2021-04-24T06:51:51.660 に答える
-1

多くの人が正解しました。ここでうまく整理し、与えられた回答に欠けている追加情報をいくつか入れます。

Constは、修飾子とも呼ばれるC言語のキーワードです。Constを任意の変数の宣言に適用して、その値が変更されないことを指定できます

const int a=3,b;

a=4;  // give error
b=5;  // give error as b is also const int 

you have to intialize while declaring itself as no way to assign
it afterwards.

読み方 ?

右から左に読むだけで、すべてのステートメントがスムーズに機能します

3つの主なもの

type a.    p is ptr to const int

type b.    p is const ptr to int 
 
type c.    p is const ptr to const int

[エラー]

if * comes before int 

2種類

1. const int *

2. const const int *

私たちは最初に見る

メジャータイプ1。constint *

3つの場所に3つのものを配置する方法3!= 6

私。*開始時

*const int p      [Error]
*int const p      [Error]

ii。開始時の定数

const int *p      type a. p is ptr to const int 
const *int p      [Error]

iii。開始時のint

int const *p      type a. 
int * const p     type b. p is const ptr to int

メジャータイプ2。constconstint *

2が似ている4つの場所に4つのものを配置する方法4!/ 2!= 12

私。*開始時

* int const const p     [Error]
* const int const p     [Error]
* const const int p     [Error]
 

ii。開始時のint

int const const *p      type a. p is ptr to const int
int const * const p     type c. p is const ptr to const int
int * const const p     type b. p is const ptr to int

iii。開始時の定数

const const int *p     type a.
const const * int p    [Error]

const int const *p      type a.
const int * const p     type c.

const * int const p    [Error]
const * const int p    [Error]

オールインワンで絞る

aと入力します。pはptrからconstint(5)

const int *p
int const *p

int const const *p
const const int  *p
const int  const *p

タイプb。pはint(2)へのconstptrです

int * const p
int * const const p;

タイプc。pはconstptrto const int(2)

int const * const p
const int * const p

ほんの少しの計算

1. const int * p        total arrangemets (6)   [Errors] (3)
2. const const int * p  total arrangemets (12)  [Errors] (6)

少し余分

int const * p、p2;

here p is ptr to const int  (type a.) 
but p2 is just const int please note that it is not ptr

int * const p、p2;

similarly 
here p is const ptr to int  (type b.)   
but p2 is just int not even cost int

int const * const p、p2;

here p is const ptr to const int  (type c.)
but p2 is just const int. 

終了した

于 2021-03-30T11:25:09.610 に答える