【问题标题】:Does redefining variables over and over again increase memory?一遍又一遍地重新定义变量会增加内存吗?
【发布时间】:2017-11-29 04:23:49
【问题描述】:

例如,如果我有一个循环

for(int i = 0; i < N; i++) {
    int a, b, c, d, e;
    cin >> a >> b >> c >> d >> e;
    foo(a, b, c, d, e);
}

int a, b, c, d, e;
for(int i = 0; i < N; i++) {
    cin >> a >> b >> c >> d >> e;
    foo(a, b, c, d, e);
}

哪一个应该更快?在第一种情况下,我在 for 循环中定义了五个变量,在第二种情况下,我在外部定义了它。

我看到过诸如 Difference between declaring variables before or in loop? 之类谈论“哪个更快”的帖子,但我不确定哪个占用的内存更少。

我并不真正关心复杂性,而是我的程序中使用的内存量。

显然,在这种情况下,这并不重要,但如果我有一个多维 for 循环并且必须定义数百万次变量怎么办?或者,如果我多次定义一个包含许多元素的大向量怎么办?

如果这个问题真的很简单,我深表歉意,因为我是 C++ 新手。任何帮助将不胜感激。谢谢大家。

【问题讨论】:

  • 您在测试上述代码时观察到了什么?你注意到你的程序在这两种情况下都使用了更多的内存吗?
  • 我会说这取决于编译器如何处理它,但如果没有优化,第二种方式可能会更好。
  • 在第一个代码 sn-p 中,您将在每次循环迭代中在堆栈上分配五个整数,然后在最后弹出它们——这需要稍长一些。但就@SpencerWieczorek 而言,现实世界中的优化器会为您处理这个问题。
  • @bobjoe628 第一种方法并没有真正使用更多的内存,它只是有一个不必要的步骤来提高每次迭代中删除和添加这些变量的性能。 (假设编译器没有处理它
  • @bobjoe628 怎么样?最重要的答案是在这里说的基本相同,编译器无论如何都会处理它。

标签: c++ performance variables memory-management initialization


【解决方案1】:

我将您的代码复制/粘贴到名为 foo.cpp 和 bar.cpp 的两个文件中:

foo.cpp

#include <iostream>

void foo(int a, int b, int c, int d, int e) {
        std::cout << a << b << c << d << e << std::endl;
}

int main(int argc, char** argv) {
        for (int i = 0; i < argc; i++) {
                int a, b, c, d, e;
                std::cin >> a >> b >> c >> d >> e;
                foo(a, b, c, d, e);
        }
        return 0;
}

bar.cpp

#include <iostream>

void foo(int a, int b, int c, int d, int e) {
        std::cout << a << b << c << d << e << std::endl;
}

int main(int argc, char** argv) {
        int a, b, c, d, e;
        for (int i = 0; i < argc; i++) {
                std::cin >> a >> b >> c >> d >> e;
                foo(a, b, c, d, e);
        }
        return 0;
}

我在没有像这样优化的情况下编译它们(如果重要的话,使用 gcc 版本 6.3):

g++ -O0 foo.cpp -o foo
g++ -O0 bar.cpp -o bar

即使没有优化,结果 foo 和 bar 也是相同的。为了确定这一点,您可以比较 objdump:

objdump -D foo > foo.txt
objdump -D bar > bar.txt
diff foo.txt bar.txt

但是,有几点需要指出:

  • int 是一种原始类型,如果说这些是类的实例,那么可能会有所不同(在性能方面,而不是内存使用方面)。这是因为如果编译器(没有优化)没有使结果相同,则循环的每次迭代都会创建和销毁实例
  • 您的变量占用了堆栈上的内存(因为您没有使用new)。即使在编译器无法从两个代码中产生相同结果的情况下,您也将使用相同数量的内存
  • 如果您改为使用new 创建变量,并且在for 循环内创建变量时不删除它们,那么变量将占用堆空间而不是堆栈空间,然后第一个代码将使用更多内存。没有理由这样做,但如果你这样做了,你仍然可以通过在每个循环结束时调用 delete 来使用相同数量的内存

【讨论】:

    【解决方案2】:

    不,每次循环迭代都将使用相同的内存。对于原始类型(例如 int),如果您不初始化它们,您甚至不会遭受这种惩罚。如果您要使用确实需要初始化的类型来执行此操作,那么第二个可能会更快(尽管如果您使用这种类型,它是否在循环内可能取决于您对实例所做的事情)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多