3

16バイトの構造体である特定のGUID用のテンプレートを特殊化したいと思います。GUIDオブジェクトには内部リンクがあるため、オブジェクト自体のアドレスは使用できませんが、オブジェクトは定数であるため、オブジェクトの内容は使用できると思いました。しかし、このサンプルコードに示されているように、これは機能しません。

struct S
{
    int const i;
};
S const s = { 42 };
char arr[s.i];

sが定数の場合、なぜsiが定数ではないのですか?回避策はありますか?

4

2 に答える 2

7

構造体の初期化はs実行時に発生する可能性があります。ただし、配列のサイズはコンパイル時に認識されている必要があります。コンパイラーはs.i、コンパイル時にの値が既知であることを(確かに)認識しないため、使用すべきでないものに変数を使用していることを認識します。問題は恒常性ではなく、配列のサイズがいつ必要になるかという問題です。

constあなたは何を意味するのか誤解しているかもしれません。これは、変数が初期化された後、変更されないことを意味するだけです。たとえば、これは合法です。

void func(int x){
    const int i = x*5; //can't be known at compile-time, but still const
    //int array[i]; //<-- this would be illegal even though i is const 
}

int main(){
    int i;
    std::cin >> i;
    func(i);
    return 0;
}

この制限を回避するために、C ++ 11ではconstexpr、コンパイル時に値を決定できることを示すようにマークを付けることができます。これはあなたが望むもののようです。

struct S
{
    int const i;
};
int main(){
    constexpr S const s = { 42 };
    char arr[s.i];
    return 0;
}

コンパイル:

$ c++ -std=c++11 -pedantic file.cpp


C99では、実行していることは合法であり、コンパイル時に配列のサイズを知る必要はありません。

struct S
{
    int const i;
};
int main(){
    struct S const s = { 42 };
    char arr[s.i];
    return 0;
}

コンパイル:

$ cc -std=c99 -pedantic file.c

于 2013-03-13T17:47:06.540 に答える
2

少なくともほとんどの場合、const実際には「一定」よりも「読み取り専用」にはるかに近いものを意味します。C89 / 90では、本質的にそれが意味するのは「読み取り専用」だけです。C ++は、それが一定である可能性があるいくつかの状況を追加しますが、それでも常に近いわけではありません(そして、残念ながら、それが重要であるときにそれが何を意味するかを正確に追跡します)。

幸いなことに、「回避策」は、どのような場合でもほぼ確実に必要な方法でコードを記述することです。

std::vector<char> arr(s.i);

結論: C ++での組み込み配列のほとんどの使用は、疑わしいと見なされるべきです。非定数式からベクトルを初期化できるという事実は、多くの利点の1つにすぎません。

于 2013-03-13T17:52:29.750 に答える