2

C++

まだ2ポインターではないconstポインター(例:T const * const)を暗黙的または明示的にキャストしたり、何か(関数など)を介して処理したり、そうでなければ変換したりしてT const * const、初期化に使用することなく、または使用する前にを生成できるかどうかを知りたいとして宣言されている変数T const * const。これどうやってするの?

T*から始めれば、1 つconst_cast(キャストが一度に 1 つしかキャストできない場合は 2 つ) で十分だと思いましたconstが、明らかにそうではありません。T const * constコード内の多くの変数は、キャストまたは関数からの戻りによる別の失敗した試みを示しています。すべてのキャストで、末尾にconst. (constの左側を*先頭const、 の右側を*末尾と呼びconstます。) キャストが失敗したため、constスルー直接初期化を強制しようとして失敗しました。これは でコンパイルされましたVC11stack-crooked.com の g++は、論理的に同等のコンソール出力を提供しますが、名前は異なりますtypeid(/*...*/).name().

#include <iostream>
#include <typeinfo>
using namespace std;

int const * const foo()
{
    return nullptr;
}

int main()
{
    int x = 7;

    auto a1 = &x;
    cout << typeid(a1).name() << endl;

    auto a2 = const_cast<int const *>(&x);
    cout << typeid(a2).name() << endl;

    auto a3 = const_cast<int * const>(&x);
    cout << typeid(a3).name() << endl;

    auto a4 = const_cast<int const * const>(&x);
    cout << typeid(a4).name() << endl;

    auto a5 = const_cast<int const * const>(a4);
    cout << typeid(a5).name() << endl;

    auto a6 = (int const * const) &x;
    cout << typeid(a6).name() << endl;

    auto a7 = static_cast<int const * const>(a4);
    cout << typeid(a7).name() << endl;

    auto a8 = reinterpret_cast<int const * const>(a4);
    cout << typeid(a8).name() << endl;

    auto a9 = foo();
    cout << typeid(a9).name() << endl;

    int const * const a10 = &x;
    cout << typeid(a10).name() << endl;
    cout << ( typeid(a10) == typeid(a4) ) << endl;

    auto a12 = a10;
    cout << typeid(a12).name() << endl;
    cout << ( typeid(a12) == typeid(a4) ) << endl;
}

期待される結果と実際の結果、および質問:

質問番号は、同じ番号のa#変数に対応しています。

  1. 期待通りの結果が得られましたint *
  2. 期待通りの結果が得られましたint const *
  3. 期待さint* constれていましたが、得られましたint*。はconst_castその末尾のconst引数を無視しましたか?その理由は? 戻り値は引数と同じ定数と型であるため、キャストは実行されましたか?
  4. 期待さint const * constれていましたが、得られましたint const*。はconst_castその末尾のconst引数を無視しましたか?その理由は?
  5. 引数の先頭const_cast<int const * const>に既に. 予想される。を得た。はその末尾の引数を無視しましたか?その理由は?consta4constint const * constint const*const_castconst
  6. 予想されるint const * const。を得int const*た。明示的なキャストが引き続き末尾を除外するのはなぜconstですか?
  7. 予想されるint const * const。を得int const*た。static_cast末尾の を除外するのはなぜconstですか?
  8. 予想されるint const * const。を得int const*た。reinterpret_cast末尾の を除外するのはなぜconstですか?
  9. 予想されるint const * const。を得int const*た。関数の戻り値を初期化しても、結果int const * constの末尾が除外されるのはなぜですか?const
  10. 予想されるint const * const。デバッガーint const*からではなく、コンソール出力から取得しました。a10として明示的に宣言されてint const * constいるのに、なぜtypeid().name()末尾の const を除外するのでしょうか? operator==では1、なぜtypeid()それ自体 (名前だけでなく) が のa10それと同等なのa4ですか? VC11 デバッガーはa10、 のタイプを としてリストしますint const * consttypeid()なぜ と のものと違うのtypeid().name()ですか? どちらが正しいですか?
  11. 変数名a11は「all」に似ているので省略。
  12. 明示的に宣言された に初期化されているため、そうであると予想a12していました。 譲りますので、まだまだです。コンソール出力とデバッガーの両方から取得しました。期待される結果と異なるのはなぜですか?int const * consta10int const * constoperator==1typeid()int const*int const*

すべてのキャスト、関数の戻り値、および初期化は、一度に 1 つのキャストのみに制限さconstれていますか? const彼らがキャストできるのはリーディングだけですか?

4

1 に答える 1

3

const_castあなたが思うように動作します。しかし、autoあなたが思っていることはしません。auto関数テンプレートのパラメーター推定と同様に機能します (実際、後者に関して定義されています)。今考えてみましょう:

template<typename T>
void f(T x);

f(42);
int const n = 42;
f(n);

どちらの呼び出しもf<int>()ではなくf<const int>()です。トップレベルの const 修飾子は、テンプレート パラメーターの推定によって無視されます。同じ理由で、この例では

auto a = 42; a = 84;
auto b = n;  b = 84;

変数aとはではなくbタイプであり、変更できます。intconst int

于 2013-10-13T04:17:38.010 に答える