为什么我的C++;代码比LeetCode上的C等效代码慢三倍? 我一直在做一些,我注意到C解决方案比C++中的完全相同的事情快了几倍。例如:

为什么我的C++;代码比LeetCode上的C等效代码慢三倍? 我一直在做一些,我注意到C解决方案比C++中的完全相同的事情快了几倍。例如:,c++,c,C++,C,更新了几个简单的示例: 给定排序数组和目标值,如果找到目标,则返回索引。如果不是,则返回按顺序插入的索引。您可以假定阵列中没有重复项。() 我的解决方案采用C语言,运行时间为3毫秒: int searchInsert(int A[], int n, int target) { int left = 0; int right = n; int mid = 0; while (left<right) { mid = (left + right)

更新了几个简单的示例:

给定排序数组和目标值,如果找到目标,则返回索引。如果不是,则返回按顺序插入的索引。您可以假定阵列中没有重复项。()

我的解决方案采用C语言,运行时间为3毫秒:

int searchInsert(int A[], int n, int target) {
    int left = 0;
    int right = n;
    int mid = 0;
    while (left<right) {
        mid = (left + right) / 2;
        if (A[mid]<target) {
            left = mid + 1;
        }
        else if (A[mid]>target) {
            right = mid;
        }
        else {
            return mid;
        }
    }
    return left;
}
int searchInsert(int A[],int n,int target){
int左=0;
int右=n;
int-mid=0;
而(左>1)| | rev<(1(-1U>>1)| | rev<(1(-1U>>1)| | rev<(1 INT|u MAX | | rev

<>现在,我想必须使用<代码> >包含与<代码>有关的东西,但是这个简单的改变似乎使执行时间从6Ms增加到19Ms,有点极端。

< p>你在C++代码片段中使用矢量的向量。向量是C++中的序列容器,就像是可以改变大小的数组,而不是“COD”。e> vector
如果您使用静态分配的数组,那会更好。您可以使用自己的数组类以及运算符[]重载,但向量在它的原始元素大小加上更多的时候它会动态调整大小。在C++中,如果你把它与C++比较,你可以使用引用来进一步减少时间。如果写得好,应该运行得更快。

最近我在C++中看到了很多关于2D数组的<<代码>矢量<代码>建议。+,我一直在向人们指出为什么这真的不是一个好主意。当拼凑临时代码时,这是一个方便的技巧,但是(几乎)从来没有任何理由将其用于真正的代码。关键是使用一个封装连续内存块的类

因此,我的第一反应可能是指出这可能是造成差异的原因。不过,在C版本中,您也使用了
int**
,这通常是与
vector
完全相同的问题的标志

因此,我决定只比较这两种解决方案

6468424
6588511

这是“C版本”与“C++版本”所用的时间,单位为纳秒

我的结果并没有显示出你所描述的差异。然后我想到检查人们在基准测试时犯的一个常见错误

18386695
42400612

请注意,第一个示例中的-O3标志已变为-O0,这将禁用优化

结论:您可能正在比较未优化的可执行文件

C++支持构建不需要开销的丰富抽象,但消除开销确实需要某些代码转换,这些转换会破坏代码的“可调试性”

这意味着调试生成避免了这些转换,因此C++调试生成通常比C样式代码的调试构建慢,因为C样式代码不使用太多的抽象。例如,当使用函数调用代替简单存储I的机器代码时,看到上述130%的放缓并不令人惊讶。指令


有些代码确实需要优化,以便即使在调试时也能获得合理的性能,因此编译器通常会提供一种模式来应用一些优化,而这些优化不会给调试器带来太多麻烦。Clang和gcc为此使用
-O1
,您可以看到,即使是这种级别的优化也基本上消除了这方面的差距在C风格代码与更多C++风格代码之间的程序:

8389992
8196935


更新:


在后面的示例中,优化不应该有什么区别,因为C++没有使用任何超越C版本所做的抽象。我猜想,解释是,这些示例是用不同的编译器或其他一些不同的编译器选项编译的。会说比较这些运行时数字是没有意义的;LeetCode显然没有产生苹果对苹果的比较。

因为您使用的是向量的向量,这意味着您的每一列(或每一行)一个单独的分配可能在一个缓存友好的位置上,也可能不在。从多个运行到平均值的时间是不是都是优化的?一些C++编译器在关闭时能够对向量进行范围检查,就像在调试构建中。你使用什么编译器选项?为什么C++解决方案被打包在一个类中,AR?你在计时器中包括了类初始化吗?说到哪一个,你如何执行执行?分配方案不同吗?C中的一个块与C++中的多个块(矢量)。无论如何,你都应该选择一个内存块(没有矢量的向量)。我不知道这是如何回答问题的:C++代码改变了向量的大小吗?为什么不这样做,那为什么会对运行时间有贡献?向量已经被引用传递了。虽然你已经做了真实的陈述,但是我不太清楚它们与当前的问题是什么相关的。C++绝对没有理由。添加到@ diutl ucc:c++原始的“编译器”输出是简单的C代码。它所做的只是将(C)+转换成C代码以供C编译器使用。没有C++为什么会慢的原因。它的原始名称(我想)是“C类”。@RobKennedy你知道为什么这个问题被否决了吗?Robinson的评论和bames53的回答基本上是一样的。我不知道你为什么问我,@Nick。Robinson的评论表明问题在于缓存局部性。Bames的回答说问题在于优化。这两件事不一样。我经常看到
std::vector
正在优化到“原始”阵列,但是,正如您所说的,您需要进行优化
class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        int left = 0;
        int right = n;
        int mid = 0;
        while (left<right) {
            mid = (left + right) / 2;
            if (A[mid]<target) {
                left = mid + 1;
            }
            else if (A[mid]>target) {
                right = mid;
            }
            else {
                return mid;
            }
        }
        return left;
    }
};
int reverse(int x) {
    long rev = x % 10;
    x /= 10;
    while (x != 0) {
        rev *= 10L;
        rev += x % 10;
        x /= 10;
        if (rev>(-1U >> 1) || rev < (1 << 31)) {
            return 0;
        }
    }
    return rev;
}
class Solution {
public:
    int reverse(int x) {
        long rev = x % 10;
        x /= 10;
        while (x != 0) {
            rev *= 10L;
            rev += x % 10;
            x /= 10;
            if (rev>(-1U >> 1) || rev < (1 << 31)) {
                return 0;
            }
        }
        return rev;
    }
};