2

最初は、メンバー変数は通常、C++ クラスでは const である必要があるという印象を受けました。ただし、オブジェクトごとに内部的にそれらの変数を変更するメンバー関数が必要な場合を除きます (変数は通常、プライベートに入れます:)。

しかし、私はずっと間違っていたかもしれないことに今気づきました。たとえば、そのようなオブジェクトに割り当てることはできなくなりました。move-assignすらできません。

std::string としましょう。あなたはこれを行うことができます:

std::string foo("foo");
foo = std::string("bar");

これは、内部的に、 std::string が非 const メンバー変数しか持たないことを意味する必要がありますよね?

私の考えは正しいですか?C++ は比較的新しいので、新しい考え方は少し奇妙です。const の目的は、私が思っていたものではないかもしれません。

それでは、constメンバー変数を持つ実際の目的は何ですか?

4

7 に答える 7

6

メンバーは通常、C++ クラスで const であってはなりませんか?

変数が「通常」宣言される方法を無視することをお勧めします。の出現頻度は、宣言しようとしている次の変数がconstであるかどうかを決定するものではありません。const

メンバーはconst、プログラムの実行全体を通じて初期化後に値が変更されないはずである必要があります。それ以外の場合、それらはすべきではありませんconst。これはデータのセマンティック プロパティであり、変数を作成するかどうかを決定するために使用する必要がある唯一の基準constは、値の変化に関する変数の性質です。

変わるかもしれませんか、それとも変わらないでしょうか? 後者の場合は必ず作ってconstください。

これは、内部的に std::string が非 const メンバー変数しか持たないことを意味する必要があります。

いいえ、それを暗示しているわけではありませんが、おそらくstd::string.

重要なことは、クラスにメンバーがあるだけではないという ことです (もちろん、そこから移動したい場合や、クラスが何らかのリソースをカプセル化している場合)。から移動されたものは変更可能です。const

オブジェクトから移動すると、残るのはスケルトンです。移動コンストラクターまたは移動代入演算子には、この移動元オブジェクトをスケルトンとして「フラグを立てる」方法が必要です。通常、これは、移動された from オブジェクトの「内臓を盗む」プロセス、つまりいくつかのポインターをコピーして null に設定するプロセスから自然に続きます。この方法では、デストラクタと代入演算子はそれらを解放しようとしません。移動元オブジェクトを「ゾンビ」としてフラグを立てるには、明らかに、変更可能なメンバー変数が必要です。

ただし、クラスにメンバーがいることに問題はありません。プログラムのセマンティクスをより明確にし、プログラムがそれを壊す可能性を低くする重要な修飾子です。必要に応じて (つまり、初期化後のプログラムの実行中に A 変数の値が変わらない場合)、それを使用してください。constconst

簡単に言えば、constメンバー変数は移動コンストラクターまたは移動代入演算子によって変更されません (実際、それらはどの関数によっても変更されません)。繰り返しますが、それは彼らが存在できないという意味ではありません。

于 2013-02-21T18:17:13.823 に答える
2

メンバー関数がそれらの変数を変更したい場合を除いて、メンバー変数は通常C++クラスではconstである必要があるという印象を受けました。

忘れているのは、デフォルトの代入演算子を含め、代入演算子メンバー関数であることです。例:

struct Foo {
    const int i = 0;

    Foo& operator =(const Foo& src)
    {
        if (&src == this)
            return *this;
        i = src.i;
        return *this;
    }
};

代入演算子はメンバー関数であるため、明らかに変更できる必要がありFoo::iます。そうでない場合、それを呼び出すことはできません。Fooオブジェクトaとを考えるとb、これは次のことを覚えておいてください。

a = b;

これは実際には構文糖衣です:

a.operator= (b);

Foo::iまた、この場合、がであるため、デフォルトの代入演算子が削除されることに注意してconstください。つまりFoo、自分で代入演算子を作成しないと、代入演算子がまったく不足します。

于 2013-02-21T18:23:23.923 に答える
1

const オブジェクトは、変更したくないオブジェクトであり、プログラムの実行中は一定のままです。クラスのコンストラクターのメンバー初期化リストでそれらに値を割り当てることができますが、それ以上はできません。異なる値を持つことができる変数がある場合は、const を使用しないでください。

于 2013-02-21T18:16:50.060 に答える
1

まず、この関連する質問への回答をご覧になることをお勧めします。

手っ取り早い答えは、const メンバー プロパティには、オブジェクトが初期化された後も変更できない値が含まれているというものです。コピー操作は、新しいオブジェクトを構築し、古いオブジェクトの値を新しいオブジェクトに割り当てるアクションを実行しようとしています (暗黙のコピー コンストラクター本体で)。解決策として最も可能性が高いのは、元のオブジェクトを引数として取り、初期化リストの const プロパティ値を初期化する明示的なコピー コンストラクターを作成することです。

コピー コンストラクターの例:

ClassWithConstantProperties( const ClassWithConstantProperties &orig) :
    constProperty1(orig.constProperty1)
    constProperty2(orig.constProperty2)
{
}

このチュートリアルでは、C++ で暗黙的に定義されたクラスのコンストラクターについて詳しく説明しており、優れた C++ リファレンス ページにもあります。

于 2013-02-21T18:29:41.120 に答える
1

オブジェクトによって異なりますが、一般に、オブジェクトのコードを記述する場合、その不変条件はユーザーが責任を負います。メンバーを使用したり参照したりすることはめったにconstありませんが、代入をサポートしていないクラスでは完全に受け入れられます。

一般に、constビットごとの const ではなく、論理 const として使用されます。また、 const は、自分自身から自分を守るものではなく、自分とクライアントの間の契約です。この意味で、const 関数を持ち、const 参照を返し、const 参照を引数として受け取ることは非常に理にかなっています。ただし、引数の最上位の const またはクラスの const は、実際にはあまり意味がありません。

于 2013-02-21T18:47:52.677 に答える
0

定数変数は、構築後にクラス内で値を変更してはならない場合に使用されます。
いくつかの例:数値定数(pi、e)と参照。

struct Database_Record
{
    Database_Record(const std::string& table_name)
      : m_table_name(table_name)
    { ; }
    const std::string& get_table_name(void) const
    {  return m_table_name; }
private:
    const std::string m_table_name;
};

データベースレコードを表す上記の構造では、レコードに関連付けられたテーブル名があり、初期化後に変更することはできません。これにより、レコードが間違ったテーブルに書き込まれるのを防ぎます。

于 2013-02-21T18:22:09.337 に答える
0

クラスのデータ メンバーは、その型のオブジェクトの状態を記述します。データ メンバーは、オブジェクトが変更されない何らかの状態を持っているconstことを意味します。これはあまり一般的ではありません。多くの場合const、メンバーもstaticです。

データ メンバーでできる唯一のことconstは、コンストラクターのメンバー初期化リストを初期化することです。

std::string別の a から a に代入できるという事実はstd::string、そのコピー代入演算子がそのデータ メンバーに対して何もしないことを意味するだけですconst(もちろんできないため)。

データ メンバーを持つクラスまたは構造体にはconst、暗黙的にデフォルト設定されたコピー代入演算子はありません。コンパイラはconstデータメンバーに割り当てることができないため、「割り当てたい場合は、自分で定義する必要があります」と表示されます。

于 2013-02-21T18:18:58.307 に答える