C#指针与C ++指针

我一直在学习编程,我选择C ++和C#编程作为第一语言。 更具体地说,我有一本旧的C书,有人让我借用,我用它来学习C#。 我使用Visual Studio Express并使用C ++和C#编写。 我感兴趣的一个领域是直接内存管理的能力。 我正在努力学习如何使用它来优化我的代码。 但是,我正在努力做到这一点,实际上看到任何真正的性能提升。 例如,以下是C#中的以下代码:

unsafe static void Main(string[] args) { int size = 300000; char[] numbers = new char[size]; for (int i = 0; i < size; i++) { numbers[i] = '7'; } DateTime start = DateTime.Now; fixed (char* c = &numbers[0]) { for (int i = 0; i < 10000000; i++) { int number = myFunction(c, 100000); } } /*char[] c = numbers; // commented out C# non-pointer version same speed as C# pointer version { for (int i = 0; i < 10000000; i++) { int number = myFunction(c, 100000); } }*/ TimeSpan timeSpan = DateTime.Now - start; Console.WriteLine(timeSpan.TotalMilliseconds.ToString()); Console.ReadLine(); } static int myFunction(ref char[] numbers, int size) { return size * 100; } static int myFunction(char[] numbers, int size) { return size * 100; } unsafe static int myFunction(char* numbers, int size) { return size * 100; } 

无论我调用哪三种方法,我都获得相同的执行速度。 我还在尝试围绕使用ref和使用指针之间的区别,除了这可能需要时间和练习。

然而,我不明白的是,我能够在C ++中产生非常显着的性能差异。 当我尝试在C ++中使用相同的代码时,我想到了以下内容:

 /*int myFunction(std::string* numbers, int size) // C++ pointer version commented out is much faster than C++ non-pointer version { return size * 100; }*/ int myFunction(std::string numbers, int size) // value version { return size * 100; } int _tmain(int argc, _TCHAR* argv[]) { int size = 100000; std::string numbers = ""; for (int i = 0; i < size; i++) { numbers += "777"; } clock_t start = clock(); for (int i = 0; i < 10000; i++) { int number = myFunction(numbers, 100000); } clock_t timeSpan = clock() - start; std::cout <> c; return 0; } 

谁能告诉我为什么我的C#代码不会受益于我对引用或指针的使用? 我一直在网上读东西,除了我被困住了。

C#已经生成了指针而没有你明确地声明它们。 每个引用类型引用(如数字变量)实际上都是运行时的指针。 使用refout关键字传递的每个参数实际上都是运行时的指针。 数组参数的确切C等价物是char **,char *和C ++。 C#没有区别。

所以你没有看到速度上的任何差异,因为实际执行的代码是相同的。

这不是它停止的地方,你从来没有对数组做过任何事情。 您调用的方法在运行时消失,就像在C或C ++编译器中一样,它将由优化器内联 。 由于您不使用数组参数,因此您也不会获得任何代码。

当您使用它们来实际处理内存时,指针对于加速程序非常有用。 您可以索引数组,并确保您永远不会支付数组边界检查。 在许多情况下,您也不会在正常使用情况下付费,如果抖动优化器知道索引始终是安全的,那么删除检查是相当明智的。 这是对指针的不安全使用,你可以随便乱写到不属于该数组的内存部分并以这种方式破坏GC堆。 用于对象引用或ref参数的指针绝不是不安全的。

查看其中任何一个的唯一真正方法是查看生成的机器代码。 Debug + Windows + Disassembly窗口。 重要的是,即使您调试代码仍然需要优化,或者您无法看到优化​​。 确保运行Release版本并使用Tools + Options,Debugging,General,取消选中“在模块加载时抑制JIT优化”选项。 需要熟悉机器代码才能理解您所看到的内容。

问题是你没有测量你认为你在测量的东西。 我可以阅读你的代码,并立即看到为什么你会得到这个结果或结果,这不仅仅是因为指针或指针。 还有许多其他因素在起作用,或者可能在起作用。 各种评论反映了这一点。

对于它的价值,一个C ++调用比另一个慢得多的主要原因是因为慢速复制std :: string而快速复制std :: string。 C#示例没有类似它们之间的差异顺序。

我的建议是,作为一个聪明但早期的程序员,你首先关注的是成为一个更好的程序员。 在您知道自己想要实现的目标之前,不要担心“优化”。

当您准备好真正理解这个问题时,您将不得不研究生成的代码。 在C#的情况下,它是MSIL,以及它在特定平台上的JIT。 在C ++的情况下,英特尔代码处理任何处理器。 直到你知道MSIL和JIT和操作码是什么,理解为什么你得到你所做的结果将很难解释。