使用常量值直接初始化数组

发布于 2024-07-14 15:35:37 字数 765 浏览 6 评论 0原文

每当您在 C# 中分配一个新数组时,

new T[length]

数组条目都会设置为默认值 T。如果 T 是引用类型或 T 的结果,则为 null如果 T 是值类型,则为 T 的默认构造函数。

就我而言,我想用值 -1 初始化一个 Int32 数组:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

因此,在为数组保留内存后,CLR 会循环遍历新分配的内存,并将所有条目设置为 default(int) = 0。之后,我的代码将所有条目设置为-1。

这使得初始化变得多余。 JIT 是否检测到这一点并忽略初始化为 0,如果没有,是否有办法直接使用自定义值初始化一部分内存?

参考 C# 数组初始化 - 使用非默认值,使用 < code>Enumerable.Repeat(value, length).ToArray() 不是选项,因为 Enumerable.ToArray 分配一个新数组,然后将值复制到其中。

Whenever you allocate a new array in C# with

new T[length]

the array entries are set to the default of T. That is null for the case that T is a reference type or the result of the default constructor of T, if T is a value type.

In my case i want to initialize an Int32 array with the value -1:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

So after the memory is reserved for the array, the CLR loops over the newly allocated memory and sets all entries to default(int) = 0. After that, my code sets all entries to -1.

That makes the initialization redundant. Does the JIT detect this and neglects the initialization to 0 and if not, is there a way to directly initialize a portion of memory with a custom value?

Referring to C# Array initialization - with non-default value , using Enumerable.Repeat(value, length).ToArray() is no option, because Enumerable.ToArray allocates a new array and copies the values to it afterwards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

少女净妖师 2024-07-21 15:35:38

如果您购买被认为有些有害的数组,那么你的问题将毫无意义,因为你会写:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));

If you buy into Arrays considered somewhat harmful, then your question would be moot as you would write:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
奢华的一滴泪 2024-07-21 15:35:38

我非常怀疑 JIT 是否会优化掉这种情况下的默认设置。 原因是这将是一个可观察到的差异。 考虑以下稍微改变的场景。

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

循环完全有可能抛出。 至少,JIT 可能无法证明事实并非如此。 如果它确实抛出并且 CLR 没有默认初始化内存,并且您仍然拥有对 obj 的引用,则结果将是可见的。

I highly doubt that the JIT will optimize away the default set for this scenario. The reason being is that this would be an observable difference. Consider the following slightly altered scenario.

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

It's entirely possible for the loop to throw. At least, it's probably not possible for the JIT to prove it doesn't. If it did throw and the CLR did not default initialize the memory, the result would be observable if you still had a reference to obj.

酒绊 2024-07-21 15:35:38

我建议使用 Array.Fill 作为用初始值填充数组的一种非常简洁的方法:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

这会将 isPrime 数组中的所有值初始化为 true

I suggest using Array.Fill as a very succint way to fill an array with an initial value:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

This initializes all values in the isPrime array to true.

冰之心 2024-07-21 15:35:38

如果您正在寻找一种内衬解决方案,那么您可以使用以下产品:

var myArray = Array.ConvertAll(new int[100], i => -1);

If you are looking for one liner solution then you could use below:

var myArray = Array.ConvertAll(new int[100], i => -1);
横笛休吹塞上声 2024-07-21 15:35:37

与 Dan 的答案类似,但不需要使用集合:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();

Similar to Dan's answer but without the need of using collections:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
长途伴 2024-07-21 15:35:37

这并不多余。

假设在初始化循环期间抛出异常。 如果 CLR 没有首先清除内存,您可能能够“看到”原始未初始化的内存,这是一个非常糟糕的主意,特别是从安全角度来看。 这就是 CLR 保证将任何新分配的内存擦除为 0 位模式的原因。

顺便说一句,同样的论点也适用于对象中的字段。

我想在这两种情况下,CLR 都可以检查在完成初始化之前您不会使数组在其他地方可见,但这是一个复杂的检查,以避免非常简单的“擦除该内存区域”。

It's not redundant.

Suppose an exception is thrown during your initialization loop. If the CLR hasn't cleared the memory first, you might be able to "see" the original uninitialized memory, which is a very bad idea, particularly from a security standpoint. That's why the CLR guarantees that any newly allocated memory is wiped to a 0 bit pattern.

The same argument holds for fields in an object, by the way.

I suppose in both cases the CLR could check that you're not going to make the array visible elsewhere before finishing initialization, but it's a complicated check to avoid a pretty simple "wipe this area of memory".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文