代码之家  ›  专栏  ›  技术社区  ›  Jacob

在循环中创建对象

  •  4
  • Jacob  · 技术社区  · 15 年前
     std::vector<double> C(4);
     for(int i = 0; i < 1000;++i)
      for(int j = 0; j < 2000; ++j)
      {   
       C[0] = 1.0;
       C[1] = 1.0;
       C[2] = 1.0;
       C[3] = 1.0;
      }
    

    许多的 比快

     for(int i = 0; i < 1000;++i)
      for(int j = 0; j < 2000; ++j)
      {
       std::vector<double> C(4);
       C[0] = 1.0;
       C[1] = 1.0;
       C[2] = 1.0;
       C[3] = 1.0;
      }
    

    我意识到这是因为 std::vector 在循环中不断地被创建和实例化,但是我觉得 优化远离 .

    它是 完全地 尽可能将变量保持在循环中是错误的?我有一种(也许是错误的)印象,认为这将为编译器提供优化机会。

    或者这可能只适用于吊舱类型,而不是 STD::载体 .

    编辑: 我使用了VC++2005(发布模式)和完全优化( /Ox )在WindowsXP上

    7 回复  |  直到 15 年前
        1
  •  3
  •   Stack Overflow is garbage    15 年前

    尽可能将变量保持在一个循环中是完全错误的吗?我有一种(也许是错误的)印象,认为这将为编译器提供优化机会。

    不,这是个很好的经验法则。但这只是一个经验法则。 最小化变量的作用域使编译器可以更自由地分配寄存器和进行其他优化,至少同样重要的是,它通常会生成更可读的代码。但它也依赖于重复的创造/破坏是廉价的,或者完全被优化掉。通常情况是这样……但并非总是如此。

    正如你所发现的, 有时 这是个坏主意。

        2
  •  2
  •   fredoverflow    15 年前

    问题是堆活动。替换 std::vector<double> C(4); 具有 std::array<double, 4> C; 它不应该再改变变量的位置了。

        3
  •  2
  •   Hitobat    15 年前

    我有一种(也许是错误的)印象,认为这将为编译器提供优化机会。

    对于内置类型(如int或double),这可能是正确的。

    这里的问题是,您使用的是向量,它需要在进入循环体时运行构造函数,而在离开时运行析构函数。由于这两种方法都是非常重要的,所以编译器无法对它们进行优化,因为您的程序将不再正确。

    举个相反的例子,想象一下如果使用一个文件对象而不是向量,这样的优化会做什么。

        4
  •  1
  •   xtofl Adam Rosenfield    15 年前

    创造 vector 在这种情况下,代价很高,因为它可能会在堆上分配一个大小为4的数组。

    如果你事先知道“局部”向量的大小,你也可以使用自动 数组 :

    for( int i = 0; i != 2000; ++i ) {
       int C[4]; // no initialization
       C[0] = 1;
       // ...
    }
    

    这样就可以降低分配空闲内存的成本。

        5
  •  1
  •   Sev    15 年前

    第二种方法是分配新的内存(在您的情况下是1000*2000次)。每一个都是堆中一个全新的内存位置(尽管并不总是新的,但可以在同一个位置)。内存分配比修改已分配内存中包含的值花费的时间更长。

    第一种方法是分配1个内存位置数组,只需修改其中的值。 如果编译器确实对此进行了优化(这并不总是如此),那么最好不要把它留给编译器,如果您可以选择自己作为程序员分配更少的内存(或更少的频率)。

        6
  •  0
  •   Kevin Le - Khnle    15 年前

    obj的作用域将在循环中,因此一旦循环完成,就无法使用它。这是另外一个例子,对象被实例化,然后随着循环的进行而被销毁。最后,除了时间被浪费在构建和销毁对象上之外,什么都没有完成。

        7
  •  0
  •   Patrick    15 年前

    首先,你应该确保设计是好的,这意味着:

    • 代码容易理解吗
    • 代码是否可以防止错误发生?
    • 代码容易扩展吗

    我认为在这种情况下,它确实意味着最好在循环中定义变量。

    只有当您有实际的性能问题时,您才可以优化代码(如果编译器还没有为您这样做),例如将变量声明放在循环之外。