1. ホーム
  2. c++

[解決済み] C++で "const "はいくつあり、どのように使われるのですか?

2022-05-17 01:46:05

質問

C++の初心者プログラマである私にとって、まだ非常に不明瞭に見える構成要素がいくつかあります。 const . これは、非常に多くの場所で使用することができ、非常に多くの異なる効果を持つので、初心者が生きて出てくることはほとんど不可能です。C++の第一人者が、様々な使い方と、それを使うべきか使わないべきかを永遠に説明してくれないでしょうか?

どのように解決するのですか?

いくつかの用途を収集しようとしています。

reference-to-constにいくつかの一時的なものをバインドし、その寿命を長くする。 参照は基底であることができます - そしてそれのデストラクタは仮想である必要はありません - 正しいデストラクタがまだ呼び出されます。

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

説明 を、コードを使って説明します。

struct ScopeGuard { 
    ~ScopeGuard() { } // not virtual
};

template<typename T> struct Derived : ScopeGuard { 
    T t; 
    Derived(T t):t(t) { }
    ~Derived() {
        t(); // call function
    }
};

template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }

このトリックは Alexandrescu の ScopeGuard ユーティリティクラスで使用されています。一旦テンポラリがスコープ外に出ると、Derived のデストラクタが正しく呼び出されます。上記のコードはいくつかの小さなディテールを見逃していますが、それがこのコードの大きな特徴です。


メソッドがこのオブジェクトの論理的な状態を変更しないことを伝えるためにconstを使用します。

struct SmartPtr {
    int getCopies() const { return mCopiesMade; }
};


コピーオンライトのクラスにはconstを使用する コピーする必要があるときとないときの判断をコンパイラが手助けしてくれるようにするためです。

struct MyString {
    char * getData() { /* copy: caller might write */ return mData; }
    char const* getData() const { return mData; }
};

説明 : 何かをコピーするとき、元のオブジェクトとコピーされたオブジェクトのデータが同じである限り、データを共有したいと思うかもしれません。しかし、どちらかのオブジェクトのデータが変更されると、今度は2つのバージョンが必要になります。1つはオリジナル、もう1つはコピーです。つまり、あなたは コピー の上に を書く を実行することで、両方のオブジェクトがそれぞれのバージョンを持つようになります。

コードの使用 :

int main() {
    string const a = "1234";
    string const b = a;
    // outputs the same address for COW strings
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

上のスニペットは、私のGCCでは同じアドレスを表示します。これは、使用するC++ライブラリがコピーオンライトを実装しているからです。 std::string . 両方の文字列は、別々のオブジェクトであるにもかかわらず、文字列データのために同じメモリを共有しています。作成方法 b を非恒等式にすると、非恒等式バージョンの operator[] のデータに影響を及ぼしてはならないので、GCCはバッキングメモリバッファのコピーを作成します。 a !

int main() {
    string const a = "1234";
    string b = a;
    // outputs different addresses!
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}


copy-constructorがconstオブジェクトとtemporaryからコピーを作成するためのものです。 :

struct MyClass {
    MyClass(MyClass const& that) { /* make copy of that */ }
};


自明な変更不可能な定数を作るために

double const PI = 3.1415;


任意のオブジェクトを値ではなく、参照で渡すために - 高価な、あるいは不可能な値による受け渡しを防ぐために

void PrintIt(Object const& obj) {
    // ...
}