Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么类的向量比有向量的类快_C++_Performance_C++17 - Fatal编程技术网

C++ 为什么类的向量比有向量的类快

C++ 为什么类的向量比有向量的类快,c++,performance,c++17,C++,Performance,C++17,他尝试了下面的例子,但不明白为什么会这样 先例 #include <iostream> #include <vector> class Ant { private: int m_worker; public: Ant(int x=0) : m_worker(x) {} int GetWorker() const { return m_worker; } }; class AntFarm { private: std::vector&

他尝试了下面的例子,但不明白为什么会这样

先例

#include <iostream>
#include <vector>

class Ant {
private:
  int m_worker;

public:
  Ant(int x=0) : m_worker(x) {}

  int GetWorker() const {
      return m_worker;
  }
};

class AntFarm {
private:
  std::vector<int> m_worker;

public:
  AntFarm() : m_worker(100) {}

  int GetWorker(int index) const {
      return m_worker.at(index);
  }
};


int main() {
  AntFarm farm{};
  std::vector<Ant> vec(100);
  Timer timer_farm{};
  Timer timer_ant{};

  timer_farm.Start();
  for(int j=0;j<10000;j++) {
      for(int i=0;i<100;i++) {
          int a = farm.GetWorker(i);   
      }
  }
  timer_farm.Stop();

  timer_ant.Start();
  for(int j=0;j<10000;j++) {
      for(const auto ant : vec) {
          int a = ant.GetWorker();
      }
  }
  timer_ant.Stop();

  std::cout << "Farm time passed = "<<timer_farm.Milliseconds() << std::endl;
  std::cout << "Ant time passed = "<<timer_ant.Milliseconds() << std::endl;
  return 0;
}
我试着用不同的方式来模拟蚂蚁农场。第一种方法是将Ant作为一个类,并将Antfarm存储在Ant的向量中。第二种方法是使用一个AntFarm类,该类中有int的向量

现在,当我调用GetWorker时,我认为第一种方法会比第二种方法慢。但事实证明,第一种方法是为什么更快

有人能解释为什么方法1比方法2快吗

编辑:


我使用MSCV编译器版本16.9.0+5e4b48a27和以下编译选项为Windows 10 x64编译:/GT/GS/GS/guard:cf$

我替换了我自己的计时器类,因为您没有提供计时器类,所以它以纳秒而不是毫秒打印

在发布版本中运行代码会产生

Farm time passed = 660100
Ant time passed = 0
因此,在第二种情况下,它显然优化了您的循环,因为在第一种情况下,它没有明显的副作用,但仍然可以做一些工作

将AntFarm::GetWorker更改为使用数组索引而不是.at()

让我们得到预期的结果

Farm time passed = 0
Ant time passed = 0
现在我们可以添加一些可见的副作用,以便代码实际运行。我只是在循环外移动了一个,然后打印出来,这样就不能优化了

timer_farm.Start();
int a;
for(int j=0;j<10000;j++) {
    for(int i=0;i<100;i++) {
        a = farm.GetWorker(i);
    }
}
timer_farm.Stop();
std::cout << a;

timer_ant.Start();
for(int j=0;j<10000;j++) {
    for(const auto ant : vec) {
        a = ant.GetWorker();
    }
}
timer_ant.Stop();
std::cout << a << "\n";

显然,在向量上使用.at()的成本更高,因为它会进行边界检查,但使用数组语法更快。

您需要指定编译方式(操作系统、编译器、编译器版本、使用的开关),以及true的其余部分(您的计时器类是什么?)。很可能是使用
.at()
(进行边界检查)而不是
[]
(不进行边界检查)负责,但无论如何,这些循环都是无用的,所以一个好的优化编译器应该将它们编译成绝对无效的循环。你在测量“玩具”代码所花费的时间,而这些代码实际上没有做任何有用的工作。这会产生误导性的结果,而且往往是毫无意义的。好吧,当我在linux下运行“玩具”代码时,我得到的时间都是0。当我根据r_ahlskog的回答改变构建类型时,我可以观察到同样的谨慎。但在windows上,无论我在调试或发布中构建了什么,它总是打印相同的时间。这仍然可以优化为
timer_farm.Start();timer_farm.Stop();很对,我有点惊讶它没有。我在午餐时把它打了出来,所以我觉得它很接近事实。
Farm time passed = 0
Ant time passed = 0
timer_farm.Start();
int a;
for(int j=0;j<10000;j++) {
    for(int i=0;i<100;i++) {
        a = farm.GetWorker(i);
    }
}
timer_farm.Stop();
std::cout << a;

timer_ant.Start();
for(int j=0;j<10000;j++) {
    for(const auto ant : vec) {
        a = ant.GetWorker();
    }
}
timer_ant.Stop();
std::cout << a << "\n";
m_worker[index]
Farm time passed = 109700
Ant time passed = 318600

m_worker.at(index)
Farm time passed = 550200
Ant time passed = 318200