如果我的推论是正确的,我想知道 arr的哪个类?如果我的推论是错误的我想知道我在哪里错了?哪个Class数组是对象?解决方案很难比较两者,它们几乎没有共同之处. C ++从C语言继承了此数组语法和行为.设计时只考虑了一个目标,只考虑了尽可能快的目标.您使用的分配"一词已经与运行时发生的情况不匹配,int [3]语法仅保留空间.确切的发生位置取决于声明的位置,在函数内部它将在堆栈框架上保留空间,在函数外部将在数据段中保留空间.在没有执行保证的情况下,不会初始化元素,运行时不会跟踪数组的大小,没有索引检查.这些功能会以最快的速度启动,否则会引发数十亿个错误和数以万计的恶意软件攻击.缓冲区溢出是C或C ++程序中的一个标准问题,当它破坏内存,随机覆盖其他变量或函数的返回地址时,会产生非常难以诊断的错误.或仅使用数据(即恶意软件攻击媒介)来指挥程序.当然不是C#方式.数组类型是.NET Framework中的引用类型,它们的存储始终是从GC堆分配的.如果数组很小(小于85KB),则为gen#0快速堆,否则为大对象堆.尽管有保证,但抖动和CLR中有很多胶水可以使它们保持尽可能快的速度:有专门的IL操作码来创建数组, Opcodes.NewArr ,抖动会将其转换为对CLR的直接调用.此帮助器函数动态创建数组类型(如果尚不存在)(与 Type.MakeArrayType()),从GC堆分配存储空间并初始化对象,设置Length属性并初始化数组成员,以便它们都具有它们的默认值(T).再次访问代码中的数组元素会生成专用的IL操作码,例如 Opcodes.LdElem .抖动将它们转换为机器代码指令,这些指令可检查数组范围并访问数组元素.其他数组成员直接调​​用内部SZArrayHelper类,该类经过优化可为一维数组生成快速可行的代码.抖动中的代码优化器寻找消除数组绑定检查的机会,这可能是因为它可以从代码中看到索引表达式不能超出范围.这通常是可能的,特别是当您使用foreach或编写使用数组的Length属性的for(;;)循环时,数组访问的速度与C中的等效速度一样快.垃圾收集器具有数组的内置知识,它在压缩堆时会重新排列引用类型的数组元素,以便可以在迭代数组的代码中顺序访问它们.在现代处理器上,非常非常重要,后者依赖于CPU高速缓存来快速访问内存.这是托管代码可以轻松击败本机C或C ++代码的地方,本机内存分配被卡在碰巧存在的任何地方.在没有安全保证的情况下,C#仍然具有模拟C数组的语法.当发现数组代码在程序的关键路径中时,可以使用它们.这些结构要求您使用 unsafe 关键字,它们与等效的C代码存在相同的问题: stackalloc 关键字可用于从堆栈中分配数组框架而不是GC堆.就像本地数组变量在C程序中一样.当您的C#代码中的本地数组产生过多的垃圾并且GC集合开始控制程序的执行时间时,这是一个回退. 已修复关键字可用于声明可访问的数组没有边界检查.需要通过方法调用生存的数组的stackalloc的替代方法.当您无法取消索引检查并且探查器告诉您它变得很关键时,这是一个后备方法.通常只有短数组(这种情况下元素访问不是主要成本)才是这种情况.请牢记以上信息来解决您的问题: 哪个类arr是对象?从第二个项目符号可以看出,数组具有专用类型,并且它是在运行时创建的,而无需在程序中显式声明.否则,CLR会保持一种错觉,即它是与元素类型密切相关的类型,就像C#语言语法一样,int数组的数组类型名称是"System.Int32 []".但是,它是CLR中不同的类型,该类在逻辑上是从System.Array派生的,而实际上是从System.SZArrayHelper派生的.对于这种类型的恶作剧,我最喜欢的短语是像鸭子一样打字的庸医". 为什么c#的设计师采用上述语法?这是语法糖,在简短易懂方面非常有效.如果在.NET 1.0中可以使用泛型,则可能看起来有所不同,我对此表示怀疑.同样值得注意的是,C#对于多维数组(如int[,])而言含糖过多,而对于锯齿状数组(如int[][])而言则不足,它们会诱使程序员编写性能不佳的代码.它们很昂贵,索引表达式需要多次乘法和绑定检查,而且以对CPU缓存非常不友好的顺序访问数组元素太容易了.int[] arr = new int[3]; // C#int arr[3]; //C++Declaration of array in c++ will allocate a block of memory for three integers.I can assume the same with language c#, but because of the following facts I can't.Every variable in c# is struct or class or enum, As Array is a class, arr should be the object of class Array.Intellisense also shows that arr has many member functions same as of functions of class Array, but Array is an abstract class, as we can not instantiate an abstract class, arr can be the object of any other class which might be implementing Array ClassIf my deduction is right, I want to knowWhich class arr is an object of?And if my deduction is wrongI want to know where am I wrong?Which Class array is an object of? 解决方案 Hard to compare the two, they have very little in common. C++ inherited this array syntax and behavior from the C language. Which was designed with only one goal in mind, only as-fast-as-possible was ever considered. The word "allocate" you use is already a poor mismatch with what happens at runtime, the int[3] syntax merely reserves space. Exactly where that happens depends on the location of the declaration, inside a function it will reserve space on the stack frame, outside it will reserve space in the data section.With no execution guarantees, the elements are not initialized, the runtime doesn't keep track of the size of the array, there is no index checking. As fast as possible, features that otherwise launched billions of bugs and tens of thousands of malware attacks. A buffer overflow is a standard problem in a C or C++ program, producing very hard to diagnose bugs when it corrupts memory, randomly overwriting other variables or the return address of a function. Or commandeer a program simply with data, the malware attack vector.Not the C# way of course. Array types are reference types in the .NET Framework, their storage is always allocated from the GC heap. The fast gen#0 heap if the array is small (less than 85KB), from the Large Object Heap otherwise. There is lots and lots of glue in the jitter and the CLR to make them still as fast as possible, in spite of their guarantees:there is dedicated IL opcode to create an array, Opcodes.NewArr, the jitter translates it to a direct call into the CLR.this helper function dynamically creates the array type if it doesn't exist yet (compare to Type.MakeArrayType()), allocates the storage from the GC heap and initializes the object, setting the Length property and initializing the array members so they all have their default(T) value.accessing the elements of the array in your code again produces dedicated IL opcodes, like Opcodes.LdElem. The jitter translates them into machine code instructions that check the array bounds and accesses the array element.other array members produce direct calls to the internal SZArrayHelper class, optimized to produce fast-as-possible code for one-dimensional arrays.the code optimizer in the jitter looks for opportunities to eliminate the array bound checks, possible when it can see from the code that the index expression cannot be out-of-bounds. This is often possible, particularly when you use foreach or write a for(;;) loop that uses the array's Length property, array access is then just as fast as the equivalent in C.the garbage collector has built-in knowledge of arrays, it rearranges array elements of a reference type when it compacts the heap so they can be sequentially accessed in code that iterates the array. Very, very important on modern processors that depend on the CPU caches to make memory access fast. This is where managed code can beat native C or C++ code handily, native memory allocations are stuck wherever they happen to exist.C# still has syntax to emulate C arrays, without the safety guarantees. You can use them when you found that the array code is in the critical path for your program. These constructs require you to use the unsafe keyword, they have the same problems as the equivalent C code:the stackalloc keyword is available to allocate an array from the stack frame instead of the GC heap. Just like a local array variable does in a C program. It is a fallback when the local arrays in your C# code produce too much garbage and GC collections start to dominate your program's execution time.the fixed keyword is available to declare arrays that can be accessed without bounds checking. The alternative for stackalloc for arrays that need to survive the method call. It is a fallback when you can't get the index checking eliminated and the profiler tells you that it becomes critical. This is generally only the case for short arrays, the kind where the element access isn't the dominant cost.Addressing your questions with the above info in mind: Which class arr is an object of?As you can tell from the 2nd bullet, an array has a dedicated type and it is created on the fly without you explicitly declaring it in your program. The CLR otherwise maintains the illusion that it is a type strongly correlated to the element type, like the C# language syntax does, the name of the array type for an array of ints is "System.Int32[]". It is however a distinct type in the CLR, a class that logically derives from System.Array and practically derives from System.SZArrayHelper. My favorite phrase for such type shenanigans is "quacks like a duck-typing". Why the designers of c# go with the above syntax?It is syntax sugar, pretty effective at being short and understandable. It might have looked different if generics would have been available at .NET 1.0, I kind of doubt it. Notable as well is that C# has a bit too much sugar for multi-dimensional arrays (like int[,]) and not enough for jagged arrays (like int[][]), they can lull a programmer into writing poorly performing code. They are expensive, index expressions require multiple multiplications and bound checks and it is way too easy to access the array elements in an order that is very unfriendly to the CPU caches. 这篇关于在C#和C ++中声明数组时有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
05-27 16:37
查看更多