6

AQList<T *>は簡単にconst-correctすることはできません。関数を考えてみましょう

void f(QList<T *> list)
{
    list[0]->constFunction();
}

fをに変更できます

void f(QList<const T *> list)

でもそれではできません

f(QList<T *>());    //Compile error

コンパイラは暗黙的ににキャストできないため、QList<T *>もうQList<const T *>。ただし、次のようにQListを明示的に再解釈できます。

template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
    return (QList<const T *> &)list;
}

これにより、constListテンプレート関数を使用して、次のように任意QList<T *>のをにキャストできます。QList<const T *>

f(constList(QList<T *>()));

正常に動作しているように見えますが、実際にこれを行うのは安全ですか?

4

2 に答える 2

8

あなたが検討しているキャスティング機能、…

template< class T >
inline QList<T const*>& constList( QList<T*> const& list )
{
    return reinterpret_cast< QList<T const*>& >(
        const_cast< QList<T*>& >( list )
        );
}

…実用的かもしれませんが(おそらく要素タイプの-nessにQList応じてオブジェクト表現を変更しません)、正確性を損なう可能性があります。constconst

constまず、リスト自体の-nessをキャストすることはconst正しくないため、元のリストを変更できますconst

しかし、その正式な議論constが削除されたとしても…

template< class T >
inline QList<T const*>& constList( QList<T*>& list )
{
    return reinterpret_cast< QList<T const*>& >(
        list
        );
}

…まだconst正当性の問題があります。

その理由は、リストが追加レベルの間接参照を構成し、関数自体がそうではないためですconst。したがって、関数を使用してconst要素へのポインタが含まれているとされるリストへの参照を取得した後、実際にあるものへのポインタをそのリストに格納できますconst。そして、元のリストを使用して、その実際のアイテムであるbangを変更できます。const

からへの暗黙の変換T**T const**がないのと同じ理由です。

このような問題なしにできることは、constオブジェクトへのポインタのリストがすでにある状態で、それらをオブジェクトにポイントさせることですconst

template< class T >
inline QList<T const*> const& constList( QList<T*> const& list )
{
    return reinterpret_cast< QList<T const*> const& >(
        list
        );
}

正式にはまだreinterpret_cast潜在的な問題がQListありますが、要素の恒常性に関する表現を専門とする人は、おそらく彼らが得たものは何でも値するでしょう。:-)

乾杯&hth。、

于 2011-06-26T10:50:45.083 に答える
3

定数の正当性の考え方は弱く、あなたが見つけたものは多くの理由の1つです。Constnessの概念は、セマンティックの1ビット(変更/変更しない)のみをキャプチャし、非常にひどく、構文コストが非常に高く、コードの重複が必要になることもあります。

この概念の問題の1つは、構成によって適切にスケーリングされないことです。たとえば、関数に非constオブジェクトのconstベクトル、constオブジェクトの非constベクトル、またはのconstベクトルを渡すことに関心がある可能性があります。 constオブジェクトと構文を正しくすることは費用がかかります...const_iteratorそれはもちろん。とは異なるので、標準のc++がどのように導入を余儀なくされたかを考えてみてconst iteratorください。

何年にもわたって、私は可能な限りすべての場所でconstの正当性を使用するという熱心な立場から、強制された場所でのみ使用するのとは反対の立場に移行しました。経験から、constの正当性に取りつかれていないコードはよりクリーンになり、constの正当性の機械は(少なくとも私にとっては)論理的なエラーを実際にキャッチすることはなく、constの正当性の機械自体に関するエラーのみをキャッチすることがわかりました。残念ながら、constの正しさは、C ++のルールでそう言われているため、C ++では使用を余儀なくされているものの1つであり、使用を避ける方法はありません。

私はこの投稿に反対票を投じるつもりですが、私の提案は、このテーマについてC++について読んだものすべてに批判的な目を向けることです。頭脳を維持し、客観的に判断します。何かが真実であることが良いからといって(たとえば、定数の正当性がプログラマーに役立つ)、残念ながら、それが本当に真実であるとは限りません。

その本に署名した名前がどんなに大きくても。

また、ある立場で世界の他のすべての地域が間違っている必要がある場合は、少なくとも少し懐疑的になることをお勧めします。ほとんどの言語は、C ++の後に生まれた言語であっても、この概念を実装していません。

于 2011-06-26T11:58:43.930 に答える