在堆栈还是堆上将数组作为函数参数?

马克·W

会员
已加入
2014年10月8日
留言内容
8
编程经验
Beginner
说我有这个:"double CalculateSomething(double [,] VeryLargArray)",该数组实际上是引用到堆上的内存的,还是整个数组都放在了函数堆栈上?如果是后者,如果您的数组很大,有没有办法防止这种情况?我认为,如果数组真的很大,将所有数据复制到堆栈将变得效率低下。
 

狂暴风暴

知名会员
已加入
2014年8月6日
留言内容
85
地点
南非鲁德普特
编程经验
10+
一个小的测试程序可以证明数组是通过引用传递的。

            int [] ar = 新 int[5];
            for (int i = 0; i < ar.Length; i++)
            {
                ar[i] = i * 2;
            }

            somefunc(ar);



        private void somefunc(int[] ar)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                ar[i]+=1;
            }
        }

如果在第一个代码块中调用somefunc()之后停止代码,则所有数组元素将增加一个。如果按值传递数组,则情况并非如此。因此没有复制。

这不能回答问题是在堆上还是在堆栈上。而且我不确定C#的答案。但是看到数组被实例化(使用 关键字),我的常识告诉我,原始数组(在第一个代码块中创建)在堆上。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,502
地点
悉尼,澳大利亚
编程经验
10+
一个小的测试程序可以证明数组是通过引用传递的。
这是混淆问题的好方法。除非您使用`ref`关键字,否则任何方法参数都将按值传递。如果对象是引用福彩12选5走势图,则传递的值是引用。当您将变量作为参数传递给方法时,默认机制始终是创建该变量内容的副本并将其传递给方法。如果变量是值福彩12选5走势图,则内容是值,以便将值复制并传递给方法。如果变量是引用福彩12选5走势图,则引用将被复制并传递给方法。就这么简单。变量包含的内容将被复制,引用福彩12选5走势图的变量将永远不会包含对象,因此引用福彩12选5走势图的对象将不会被复制。
 

马克·W

会员
已加入
2014年10月8日
留言内容
8
编程经验
Beginner
好吧,但是"int[] ar"引用福彩12选5走势图还是值福彩12选5走势图?我在这里有些困惑。如果我谷歌我发现"数组是C#中的参照福彩12选5走势图",但是我有一些疑问,因为在C ++中类似"int[]" is passed by value, and you should pass it as a pointer for performance. Does something like that apply for C# ? Also you in C# you have the Array type, but is int [] of that same type? Like you have the int primitive and the a class corresponding to int if it is boxed.
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,502
地点
悉尼,澳大利亚
编程经验
10+
Okay, but is "int[] ar"引用福彩12选5走势图还是值福彩12选5走势图?我在这里有些困惑。如果我谷歌我发现"数组是C#中的参照福彩12选5走势图",但是我有一些疑问,因为在C ++中类似"int[]" is passed by value, and you should pass it as a pointer for performance. Does something like that apply for C# ? Also you in C# you have the Array type, but is int [] of that same type? Like you have the int primitive and the a class corresponding to int if it is boxed.

所有数组都是引用福彩12选5走势图。引用的存在使您可以像对待外部对象一样对待它,而将其当作内部指针一样对待。就像属性实际上是方法一样,但它们似乎是外部的一个字段。引用实际上是指针,但似乎是外部对象。它不是那么简单,但是可以这样思考。您唯一要问的问题是某物是引用福彩12选5走势图(即类或委托)还是值福彩12选5走势图(即结构或枚举)。两者之间没有任何关系。它可以是一种,也可以告诉您如何使用。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,502
地点
悉尼,澳大利亚
编程经验
10+
好的,如果没有复制,出于性能原因,添加ref就像在C ++中将其作为指针传递一样,是没有用的。既然如此,触发了我的问题。
关于何时使用out和ref的规则非常简单:

如果只想使用参数将值或对象从方法中传递出去,则使用`out`。
如果要传入一个值或对象,然后传出另一值或对象,请使用“ ref”。
如果您希望能够修改方法内部的现有值福彩12选5走势图,并使该更改影响原始值,请使用“ ref”。
在所有其他情况下,请使用默认机制,即按值传递。

这就是您需要考虑的全部。只有值福彩12选5走势图对象在通过值传递时才被复制,这永远不会成为问题,因为您应该遵循Microsoft的建议,即值福彩12选5走势图只能为16个字节或更小。
 

马克·W

会员
已加入
2014年10月8日
留言内容
8
编程经验
Beginner
永远不会成为问题,因为您应该遵循Microsoft的建议,即值福彩12选5走势图只能为16个字节或更小。
好的。但是,如果遇到假设的情况,即我之前的程序员制作了一个巨大的结构,并将其放入函数参数中,该怎么办? ..实际上,我想您会说:将其重新创建为一个类,不要将ref用作性能补丁,对吗?但理论上使用ref会有所帮助。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,502
地点
悉尼,澳大利亚
编程经验
10+
好的。但是,如果遇到假设的情况,即我之前的程序员制作了一个巨大的结构,并将其放入函数参数中,该怎么办? ..实际上,我想您会说:将其重新创建为一个类,不要将ref用作性能补丁,对吗?但理论上使用ref会有所帮助。

有时出于实用原因需要做错事,这就是其中一种情况。但是,这种情况应该极为罕见。
 
最佳 底部