C++コア準則ES.50:const属性を削除する変換は実行しない

6858 ワード

ES.50: Don't cast away const
ES.50:const属性を削除する変換は実行しない
 
Reason
It makes a lie out of const. If the variable is actually declared const, modifying it results in undefined behavior.
これにより、コードは定数属性の制約を回避します.変数が実際に定数属性を持っている場合、変更すると定義されていない動作になります.
 
Example,bad(裏面例)
void f(const int& x)
{
    const_cast(x) = 42;   // BAD
}

static int i = 0;
static const int j = 0;

f(i); // silent side effect
f(j); // undefined behavior

Example(例)
Sometimes, you may be tempted to resort to const_cast to avoid code duplication, such as when two accessor functions that differ only in const-ness have similar implementations. For example:
時々constを借りたいかもしれませんcastは、constプロパティの異なるアクセスメソッドのみを使用して、2つの記述実装が類似しているなど、コードの重複を回避します.例:
class Bar;

class Foo {
public:
    // BAD, duplicates logic
    Bar& get_bar() {
        /* complex logic around getting a non-const reference to my_bar */
    }

    const Bar& get_bar() const {
        /* same complex logic around getting a const reference to my_bar */
    }
private:
    Bar my_bar;
};

Instead, prefer to share implementations. Normally, you can just have the non-const function call the const function. However, when there is complex logic this can lead to the following pattern that still resorts to a const_cast:
より良い方法は、共有実装方法です.通常、非常量関数に定数関数を呼び出すだけでいいです.しかし、論理が複雑である場合、この方法は次のコードモードをもたらし、const_を借りる必要がある.cast.
class Foo {
public:
    // not great, non-const calls const version but resorts to const_cast
    Bar& get_bar() {
        return const_cast(static_cast(*this).get_bar());
    }
    const Bar& get_bar() const {
        /* the complex logic around getting a const reference to my_bar */
    }
private:
    Bar my_bar;
};

Although this pattern is safe when applied correctly, because the caller must have had a non-const object to begin with, it's not ideal because the safety is hard to enforce automatically as a checker rule.
この方式は正しく実現される場合安全であるが,呼び出し者は非常に量のオブジェクトを用意しなければならない.このような安全性は自動的に実行されるルールで保証することが困難であるため、理想的ではない.
Instead, prefer to put the common code in a common helper function -- and make it a template so that it deduces const. This doesn't use any const_cast at all:
より良い方法は、共通コードを共通の補助関数に配置し、補助関数をテンプレート関数として設計することです.この方式はconst修飾を必要としない.const_は必要ありませんcastです.
class Foo {
public:                         // good
          Bar& get_bar()       { return get_bar_impl(*this); }
    const Bar& get_bar() const { return get_bar_impl(*this); }
private:
    Bar my_bar;

    template           // good, deduces whether T is const or non-const
    static auto get_bar_impl(T& t) -> decltype(t.get_bar())
        { /* the complex logic around getting a possibly-const reference to my_bar */ }
};

Exception(例外)
You may need to cast away const when calling const-incorrect functions. Prefer to wrap such functions in inline const-correct wrappers to encapsulate the cast in one place.
定数を受け入れない関数を呼び出す場合は、変換によって定数属性を削除する必要があります.このような関数は、変換を1つの場所に制限するために、定数を必要とする行にカプセル化されることが望ましい.
 
Example(例)
Sometimes, "cast away const"is to allow the updating of some transient information of an otherwise immutable object. Examples are caching, memoization, and precomputation. Such examples are often handled as well or better using mutable or an indirection than with a const_cast.
定数属性を削除する変換は、一時的に情報の更新を許可するために使用される場合があり、他の場合は変更できないオブジェクトです.このような例には、キャッシュ、メモ、前処理などが含まれる.このような場合、mutableまたは間接操作を使用してもよく、const_を使用するよりもcastのほうがいいです.
Consider keeping previously computed results around for a costly operation:
高コスト計算のために計算結果を長期保存する場合を考慮します.
int compute(int x); // compute a value for x; assume this to be costly

class Cache {   // some type implementing a cache for an int->int operation
public:
    pair find(int x) const;   // is there a value for x?
    void set(int x, int v);             // make y the value for x
    // ...
private:
    // ...
};

class X {
public:
    int get_val(int x)
    {
        auto p = cache.find(x);
        if (p.first) return p.second;
        int val = compute(x);
        cache.set(x, val); // insert value for x
        return val;
    }
    // ...
private:
    Cache cache;
};

Here, get_val() is logically constant, so we would like to make it a const member. To do this we still need to mutate cache, so people sometimes resort to a const_cast:
ここで、get_val()は論理的に定数関数であるべきであるため,定数メンバーとして設計することを望んでいる.そのため、キャッシュの内容を変更する必要があるため、const_を利用することがあります.cast:
class X {   // Suspicious solution based on casting
public:
    int get_val(int x) const
    {
        auto p = cache.find(x);
        if (p.first) return p.second;
        int val = compute(x);
        const_cast(cache).set(x, val);   // ugly
        return val;
    }
    // ...
private:
    Cache cache;
};

Fortunately, there is a better solution: State that cache is mutable even for a const object:
幸いなことに、cacheをmutableと宣言する(constオブジェクトでも有効):
class X {   // better solution
public:
    int get_val(int x) const
    {
        auto p = cache.find(x);
        if (p.first) return p.second;
        int val = compute(x);
        cache.set(x, val);
        return val;
    }
    // ...
private:
    mutable Cache cache;
};

An alternative solution would be to store a pointer to the cache:
もう1つの解決策はcacheをポインタとして保存することです.
class X {   // OK, but slightly messier solution
public:
    int get_val(int x) const
    {
        auto p = cache->find(x);
        if (p.first) return p.second;
        int val = compute(x);
        cache->set(x, val);
        return val;
    }
    // ...
private:
    unique_ptr cache;
};

That solution is the most flexible, but requires explicit construction and destruction of *cache (most likely in the constructor and destructor of X).
このスキームはより弾力性があるが,cacheオブジェクトの明示的な構造と解析が必要である(最も可能な位置はXの構造関数と解析関数である)
In any variant, we must guard against data races on the cache in multi-threaded code, possibly using a std::mutex.
すべての変数について、std::mutexを使用して、マルチスレッドプログラミング時にcache上でデータ競合が発生することを防止する必要があります.
 
Enforcement(実施提案)
  • Flag const_casts.
  • タグconst_cast.
  • This rule is part of the type-safety profile for the related Profile.
  • このガイドラインは、タイプセキュリティグループおよび関連グループの一部である.

  •  
    テキストリンク
    https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es50-dont-cast-away-const
     
     
    本文は役に立つと思いますか?もっと多くの人に褒めて分かち合うことを歓迎します.
    更新された文章をもっと読んで、微信の公衆番号【対象に向かって考える】に注目してください.