7

私は次のコードを持っています:

import std.stdio;

int main(string[] args)
{
   int[3] my_array = [1, 2];
   return 0;
}

これは正常にコンパイルされ、実行時に中止され、次のエラーが発生します。

arrays_init
object.Exception@src/rt/arraycat.d(31): lengths don't match for array copy
----------------
arrays_init(_Dmain+0x64) [0x416bbc]
arrays_init(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x1c) [0x418c5c]
arrays_init(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x4185d6]
arrays_init(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x3b) [0x418ca3]
arrays_init(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x4185d6]
arrays_init(main+0xd1) [0x418561]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f60bc41d30d]

配列リテラルに3つの項目がある場合、これは正常に実行されるため、配列リテラルは静的配列のサイズと一致する必要があるようです。しかし、両方のサイズはコンパイル時に計算できるため、これでコンパイルエラーが発生することはありませんか?

4

3 に答える 3

9

配列リテラルはタイプT[]です。つまり、コンパイル時にサイズを認識しない動的配列です。

コードは、これがコンパイルされるのと同じ理由でコンパイルされます。

void foo(int[] xs)
{
    int[3] ys = xs;
    ...
}

コンパイラは単にその大きさを知りませんxs

あなたの場合、すべての情報がそこにあるので、コンパイラーはコンパイル時に知ることができますが、それはコンパイラーがしなければならないことを超えて行きます。コードを厳密に解釈すると、型の不一致がないため、コンパイルされます。

動的配列である配列リテラルのもう1つの副作用は、コードが実際にメモリを割り当てることです。ヒープに動的配列を割り当て、静的配列にコピーしてから、ガベージコレクションサイクルを待ってからメモリを再利用する必要があります。タイトなループでそのようなアレイを初期化する場合、これはパフォーマンスの低下の原因となる可能性があります。

繰り返しになりますが、コンパイラーは割り当てを回避できますが、DMDは少なくとも現在のバージョン(2.060)では回避できません。

于 2012-12-18T14:31:54.063 に答える
7

これは、[1, 2](動的配列)のタイプが配列内の要素の数を保持しないため、コンパイラが割り当て(=)に到達するまでに、右側の式に含まれる要素の数がわからないためです。側。

簡単に言えば、コンパイラは単純に十分に賢くはありません。

于 2012-12-18T12:08:22.727 に答える
0

おそらくこの行のため:

int[3] my_array = [1, 2];

左側では、配列内に3つの値を示しています。つまり、を定義static array of 3 intsしていますが、2つの値のみを割り当てています。

次のように変更します。

int[3] my_array = [1, 2, 3];

そして問題は解決されるべきです。

于 2012-12-18T11:38:45.280 に答える