c#指针vs. c++指针

本文关键字:指针 c++ vs | 更新日期: 2023-09-27 18:02:41

我一直在学习编程,我选择了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 << timeSpan;
char c;
std::cin >> c;
return 0;
}

谁能告诉我为什么我的c#代码没有受益于我使用的引用或指针?我一直在网上看一些东西,除了我卡住了。

c#指针vs. c++指针

c#已经生成了指针,而无需显式声明它们。每个引用类型引用,比如numbers变量,实际上在运行时都是一个指针。使用refout关键字传递的每个参数实际上在运行时都是指针。与你的数组参数完全等价的C语言是char**, char*&在c++中。在c#中没有区别。

所以你看不到任何速度上的差异,因为实际执行的代码是一样的。

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

当您使用

指针来实际寻址内存时,

指针对于加快程序非常有用。您可以索引数组,并确保您永远不会为数组边界检查付费。在许多情况下,在正常使用中您也不会为此付费,如果抖动优化器知道索引总是安全的,它就会相当聪明地删除检查。这是不安全的使用指针,您可以很容易地将不属于数组的内存部分涂入,并以这种方式破坏GC堆。用于对象引用或ref参数的指针从来不是不安全的。

查看这些的唯一方法是查看生成的机器码。调试+ Windows +反汇编窗口。重要的是,即使您调试了代码,或者无法看到优化结果,也要允许代码仍然得到优化。确保运行Release build并使用Tools + Options, Debugging, General,取消"在模块加载上抑制JIT优化"选项。要理解所看到的内容,需要对机器码有一定的了解。

问题是你没有衡量你认为你在衡量的东西。我可以读一下你的代码,立刻明白为什么你会得到这个结果或那个结果,这不仅仅是因为指针或非指针。还有很多其他因素在起作用,或者可能在起作用。各种注释反映了这一点。

无论如何,一个c++调用比另一个慢得多的主要原因是慢的调用复制了std::string,而快的调用没有。c#示例之间没有任何类似的顺序差异。

我的建议是,作为一个聪明但处于早期阶段的程序员,你首先要专注于成为一个更好的程序员。在你知道你想要达到什么目标之前,不要担心"优化"。

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