21

または、それらを変更することに対する他の保護がありますか?

それらが読み取り専用メモリにある場合は理にかなっています-それがそれらを作成する理由constですよね?

4

9 に答える 9

18

constはコンパイル時の構造であり、実行時には不明です。プログラマーが自分のプログラムについて推論するのを助け、変更されるべきではないものを変更することによってバグが導入されるのを防ぐためだけに存在します。 constこの変数の変更を許可しないことをコンパイラーに伝え、コンパイラーはそれを強制します。

于 2013-08-05T12:23:36.480 に答える
12

いいえ、そうである必要はありません。constコンパイル時であり、コンパイラが何らかの最適化を実行できるようにします。ただし、変数を読み取り専用のメモリ ロケーションに配置することは必須ではありません。

Undefined Behaviorであるこの例を参照してください(指摘してくれた Dyp に感謝します)。

#include <iostream>

int     main()
{
  const int bla = 42;
  int       *ptr = const_cast<int *>(&bla);

  std::cout << *ptr << std::endl;
  *ptr = 21;
  std::cout << *ptr << std::endl;
}

42とが出力されます21が、クラッシュする可能性もあります。

これを見てください:

#include <iostream>

int     main()
{
  const int bla = 42;
  int       *ptr = const_cast<int *>(&bla);

  std::cout << bla << std::endl;
  *ptr = 21;
  std::cout << bla << std::endl;
}

私のコンパイラでは、コンパイラがいくつかの最適化を行ったため、この出力42と. 42が原因でクラッシュする可能性があることに注意してください*ptr = 21

于 2013-08-05T12:27:13.147 に答える
6

コンパイラが aconstを読み取り専用メモリにすることができない場合がたくさんあります (そもそもシステムに読み取り専用メモリがあると仮定して)。実際、ほぼすべてのコンパイラは、原則として、const通常の変数と同様に、オブジェクトを通常のデータ (またはスタック) メモリに格納すると考えています。

の主な目的はconst、値を変更したくない、または変更することを想定していない意図をコンパイラで宣言することです。const限られた状況下で、コンパイラが変数を読み取り専用メモリに配置できない理由はわかりません。しかし、私もこれに依存しません-標準は確かにこれを可能にします。最初にマークされたオブジェクトからconst_castremoveを使用し、それに書き込むことは未定義の動作であると述べているためです(したがって、コンパイラがを使用して元の値を削除した後に値を変更できるようにするため、「読み取り専用メモリに書き込もうとしたためクラッシュ」が発生する可能性があります)。constconstconst_castconst

しかし、これを考慮してください:

class X
{
   int x;
  public:
   X(int v) : x(v) {}
}

int c = rand();

const X a(c+1);
const X b(c+2); 

この場合、コンパイラはcから取得した の値を認識できないため、コンパイル時にrand初期化aおよびコンパイルできません。b

于 2013-08-05T12:50:01.667 に答える
4

このconstキーワードには、次の 2 つの用途があります。

  1. よく知られている「このオブジェクトの状態を変更しないことを約束します」
  2. 特別な規則として、コンパイラ、オブジェクトがメンバーを持たない (つまり、オブジェクト全体がオブジェクトの状態である)const限り、定義が読み取り専用メモリにあるオブジェクトを配置できます。mutable

そのためconst_cast、const 修飾子を削除することは許可されていませんが、オブジェクト定義自体がそうではないことが要件ですconstウィキペディアの const の正確性については、「ただし、それ自体が const として宣言されているオブジェクトを const_cast を使用して変更しようとすると、ISO C++ 標準に従って未定義の動作が発生する」と記載されています。

于 2013-08-05T13:19:13.753 に答える
3

C++ 標準は、オブジェクトが読み取り専用メモリにあることを保証していないだけでなくconst、以下で説明するように、実装を完全に実装することは困難です。

C++ 実装constでは、アドレスが読み取り専用メモリに取得される自動保存期間を持つオブジェクトを配置することは困難です。これは、それぞれのオブジェクトが異なるアドレスを持つ必要があるためです (それらのポインターが等しくない必要があるため)。したがって、そのような各オブジェクトは、それが含まれるブロックが実行されるたびに作成する必要があります。

もしconstオブジェクトのアドレスが取得されない場合、コンパイラはメモリ内の単一のインスタンスのみを使用して (C++ 計算モデルで) 複数のインスタンスを実装できます (すべてのインスタンスは同一であり、変更されないため)。そのため、このようなオブジェクトは、プログラムの起動時に (おそらくプログラム ファイルの定数データ セクションからロードすることによって) 1 回作成し、読み取り専用としてマークし、プログラムの実行中はそのままにしておくことができます。ただし、オブジェクトのアドレスが取得される (そして観察可能な方法で使用される) 場合、コンパイラはオブジェクトの個別のインスタンスをそれぞれ作成する必要があります (または、1 つのインスタンスが複数のアドレスを持つように「偽造」する必要があります)。一般に、コンパイラは、ブロックの実行が同時にいくつ存在するかを予測できません (たとえば、再帰的な関数呼び出しがある場合)。したがって、プログラムの起動時に、必要なオブジェクトのすべてのインスタンスを作成することはできません。

オブジェクトを作成するには、オブジェクトの初期値を書き込むためにメモリを変更する必要があります。したがって、const自動保存期間を持つオブジェクトを読み取り専用メモリに配置するには、メモリを読み取り専用から書き込み可能に、またはその逆に頻繁に変更する必要があります。新しいオブジェクトを作成するには、プログラムは読み取り専用メモリを書き込み可能メモリに変更し、新しいオブジェクトの初期値を書き込み、メモリを読み取り専用に戻す必要があります。

さらに、これにより、シグナル ハンドラのないシングル スレッド プログラムに対してのみ、読み取り専用メモリのように見えます。複数の実行スレッドまたは単一のハンドラーを持つプログラムは、書き込み可能な状態にある間、メモリを監視できる場合があります。

于 2013-08-05T13:46:55.687 に答える
2

標準に関する限り、const書き込み保護された RAM に変数を配置する必要はありません。const基本的には、コンパイラが強制するドキュメントにすぎません。

実際には、コンパイル時に値を完全に計算できる場合、コンパイラは通常、const変数に対して読み取り専用ストレージを使用します。それ以外の場合は、他のすべてのものと同じ読み取り/書き込みヒープまたはスタックに配置されます。

于 2013-08-05T12:27:04.147 に答える
2

いいえ。メンバーを持つconstオブジェクトを検討してください。mutable前述のように、const は、プログラマーが意図を伝えるのに役立つコンパイル時の構成要素です。

于 2013-08-05T12:28:30.373 に答える
1

constはコンパイラのマークです。コンパイル中に、コンパイラは定数を別のグループに追加し、それを変更しようとする試みをチェックします。一部の関数がそれを行おうとすると、コンパイラ エラーが発生します。

ただし、ポインターを使用してコンパイラーをだまして値を変更することは可能ですが、その結果、コンパイラーではなく自分 (または同僚) をだますことになります。constconst_cast

const私が言ったように、価値を変える方法を探していた私の友人に。constコンパイラ専用ではなく、コンパイラよりも開発者向けです。どのデータが変更されないかを示しているからです。

于 2013-08-08T07:20:24.220 に答える
1

それらが読み取り専用メモリにある場合、有用で意味のあるものになることが妨げられるためconst_cast、次のようなコードは不可能であり、const変数を非constパラメーターで関数に渡します。

void print (char * str)
{
    cout << str << endl;
}

int main () 
{
    const char * c = "test text";
    print ( const_cast<char *> (c) );
    return 0;
}

print 関数は、最初に定義されたconstvariableの値を実際に変更する可能性があることに注意してくださいc

于 2013-08-05T12:41:56.107 に答える