C++ 矢量访问速度,哪种方法更快?

C++ 矢量访问速度,哪种方法更快?,c++,performance,pointers,vector,C++,Performance,Pointers,Vector,我很好奇哪种方法访问向量更快 为了简单起见,假设我有两个对象:Player和Ship 有一个玩家指针向量向量玩家,每个玩家对象包含一个飞船指针向量向量飞船,然后每个飞船都有几个可以调用的函数,依此类推 在这些情况下,直接访问这些功能是否更快?或者创建一个临时对象指针来访问所有内容 这样做是否更快: for (int i = 0; i < players.size(); i++) { for (int j = 0; j < players.at(i)->ships.siz

我很好奇哪种方法访问向量更快

为了简单起见,假设我有两个对象:
Player
Ship

有一个玩家指针向量
向量玩家
,每个玩家对象包含一个飞船指针向量
向量飞船
,然后每个飞船都有几个可以调用的函数,依此类推

在这些情况下,直接访问这些功能是否更快?或者创建一个临时对象指针来访问所有内容

这样做是否更快:

for (int i = 0; i < players.size(); i++)
{
    for (int j = 0; j < players.at(i)->ships.size(); j++)
    {
        players.at(i)->ships.at(j)->update();
        if (
               (players.at(i)->ships.at(j)->get_x() > 0)    &&
               (players.at(i)->ships.at(j)->get_x() < screen_x)    &&
               (players.at(i)->ships.at(j)->get_y() > 0)    &&
               (players.at(i)->ships.at(j)->get_y() < screen_y)
           )
        {
            players.at(i)->visible.push_back(j);
        }
    }
}
for(int i=0;iships.size();j++)
{
players.at(i)->ships.at(j)->update();
如果(
(players.at(i)->ships.at(j)->get_x()>0)&&
(players.at(i)->ships.at(j)->get_x()ships.at(j)->get_y()>0)&&
(players.at(i)->ships.at(j)->get_y()可见。向后推(j);
}
}
}
或者,创建临时指针以便不需要不断访问向量会更快:

for (int i = 0; i < players.size(); i++)
{
    Player* play = players.at(i);
    for (int j = 0; j < play->ships.size(); j++)
    {
        Ship* ship = play->ships.at(j);
        ship->update();

        int ship_x = ship->get_x();
        int ship_y = ship->get_y();
        if (
               (ship_x > 0)    &&
               (ship_x < screen_x)    &&
               (ship_y > 0)    &&
               (ship_y < screen_y)
           )
        {
            play->visible.push_back(j);
        }
    }
}
for(int i=0;iships.size();j++)
{
Ship*Ship=play->ships.at(j);
ship->update();
int ship_x=ship->get_x();
int ship_y=ship->get_y();
如果(
(船舶x>0)&&
(装运x<屏幕x)&&
(船舶y>0)&&
(发货日期<屏幕日期)
)
{
播放->可见。向后推(j);
}
}
}
我知道第二个在视觉上更整洁,但不知道它是否一定更快


想法?

你应该检查一下,看看哪个更快

它可能是第一个,也可能是第二个。如果大多数船只的X坐标为负,这肯定是第一次


但是,如果你觉得第二个更好(我也一样),那就坚持下去。当出现实际性能问题时,请担心性能。

您应该检查哪一个更快

它可能是第一个,也可能是第二个。如果大多数船只的X坐标为负,这肯定是第一次


但是,如果你觉得第二个更好(我也一样),那就坚持下去。当出现实际的性能问题时,请担心性能。

我认为您在这里要受优化编译器的摆布。任何一个都可能更快,这取决于它如何得到优化

  • 在第一个版本中,编译器可能会决定 拉出
    players.at(i)->ships.at(j)
    common子表达式, 可能是通过
    get_x()
    get_y()
    将其转化为某种东西 看起来很像你的第二个版本

  • 在第二个版本中,重新排序可能会移动
    int ship\u y=ship->get\u y()
    进入循环条件,以便 与
    ship_y>0
    短路

  • 在这两种情况下,它可能决定将整个短路变为有条件的 转换成一系列快速的按位和指令,消除 分支机构


但我的猜测是,无论哪种方式,你都不会看到太大的差异。尝试转储汇编代码以进行比较,当然,还要对其进行分析。

我认为您在这里的优化编译器将任由您摆布。任何一个都可能更快,这取决于它如何得到优化

  • 在第一个版本中,编译器可能会决定 拉出
    players.at(i)->ships.at(j)
    common子表达式, 可能是通过
    get_x()
    get_y()
    将其转化为某种东西 看起来很像你的第二个版本

  • 在第二个版本中,重新排序可能会移动
    int ship\u y=ship->get\u y()
    进入循环条件,以便 与
    ship_y>0
    短路

  • 在这两种情况下,它可能决定将整个短路变为有条件的 转换成一系列快速的按位和指令,消除 分支机构


但我的猜测是,无论哪种方式,你都不会看到太大的差异。尝试转储程序集代码以进行比较,当然,还要分析它。

谢谢大家提供的信息。由于没有明确的“选项a肯定比选项B快”,我采纳了你的建议,做了台架测试

这是我编的一些代码

基本上,它创造了100名玩家。每个玩家有一个100艘船的向量。每艘船有100名船员。(一旦运行,它将消耗大约500MB的RAM)

我运行了未优化和优化的测试(O3标志)

测试1是链指针(即玩家->船->船员->编号等) 测试2与测试1相同,但我用操作符[]替换了所有的.at()。 测试3使用临时指针访问所有内容

我多次运行每个测试并平均结果。 以下是我的结果:

未优化:

Test 1:  13000
Test 2:  5500
Test 3:  2800
优化:

Test 1:  1050
Test 2:  650
Test 3:  450
结果表明,在所有情况下,优化都大大提高了速度。 不管是优化还是未优化,.at()都会明显降低速度。使用操作符[]的速度要快得多。 但最终,在所有情况下,使用临时指针都是最快的

#include <vector>
#include <ctime>
#include <iostream>

using namespace std;

class People
{
    public:
        vector<int> number;
};

class Ship
{
    public:
        Ship(int f);
        vector<People*> crew;
        int get_x();
        int get_y();

    private:
        int x;
        int y;
};

Ship::Ship(int f)
{
    //Assign some nonsense for testing purposes
    x = f * 50;
    y = f * 75;
}

int Ship::get_x()
{
    return x;
}

int Ship::get_y()
{
    return y;
}

class Player
{
    public:
    vector<Ship*> ships;
};

int main(int argc, char *argv[])
{
    vector<Player*> players;

    int start, end;
    unsigned int i, j, k, l;

    //Create 100 players, each with 100 ships, and each ship with 100 crew.
    for (i = 0; i < 100; i++)
    {
        Player* play = new Player;
        players.push_back(play);
        for (j = 0; j < 100; j++)
        {
            Ship* new_ship = new Ship(j);
            play->ships.push_back(new_ship);
            for (k = 0; k < 100; k++)
            {
                People* newbie = new People;
                new_ship->crew.push_back(newbie);
                for (l = 0; l < 100; l++)
                {
                    newbie->number.push_back(0);
                }
                newbie->number.clear();
            }
        }
    }    


    //Test 1


    start = clock();

    for (i = 0; i < players.size(); i++)
    {
        for (j = 0; j < players.at(i)->ships.size(); j++)
        {
            for (k = 0; k < players.at(i)->ships.at(j)->crew.size(); k++)
            {
                for (l = 0; l < 100; l++)
                {
                    //Give each crew some number to hold on to.
                    players.at(i)->ships.at(j)->crew.at(k)->number.push_back(players.at(i)->ships.at(j)->get_x() * players.at(i)->ships.at(j)->get_y() + l);
                }
                //Clear the number list for the next test.
                players.at(i)->ships.at(j)->crew.at(k)->number.clear();
            }
        }
    }
    end = clock();

    cout << "Test 1:   "  << (end - start) << endl;


    //Test 2

    start = clock();

    for (i = 0; i < players.size(); i++)
    {
        for (j = 0; j < players[i]->ships.size(); j++)
        {
            for (k = 0; k < players[i]->ships[j]->crew.size(); k++)
            {
                for (l = 0; l < 100; l++)
                {
                    players[i]->ships[j]->crew[k]->number.push_back(players[i]->ships[j]->get_x() * players[i]->ships[j]->get_y() + l);
                }
                players[i]->ships[j]->crew[k]->number.clear();
            }
        }
    }
    end = clock();

    cout << "Test 2:   "  << (end - start) << endl;


    //Test 3


    start = clock();

    for (i = 0; i < players.size(); i++)
    {
        Player* temp_play = players.at(i);
        for (j = 0; j < temp_play->ships.size(); j++)
        {
            Ship* temp_ship = temp_play->ships.at(j);
            for (k = 0; k < temp_ship->crew.size(); k++)
            {
                People* temp_crew = temp_ship->crew.at(k);
                for (l = 0; l < 100; l++)
                {
                    temp_crew->number.push_back(temp_ship->get_x() * temp_ship->get_y() + l);
                }
                temp_crew->number.clear();
            }
        }
    }
    end = clock();

    cout << "Test 3:   "  << (end - start) << endl;

    return 0;
}
#包括
#包括
#包括
使用名称空间std;
阶级人士
{
公众:
向量数;
};
班轮
{
公众:
船舶(INTF);
航母队;
int get_x();
int get_y();
私人:
int x;
int-y;
};
船舶:船舶(INTF)
{
//为测试目的分配一些无用的东西
x=f*50;
y=f*75;
}
int Ship::get_x()
{
返回x;
}
int Ship::get_y()
{
返回y;
}
职业选手
{
公众:
矢量船;
};
int mai
auto is_visible = [=](Ship const &s) { return s.get_x() > 0 && s.get_x() < screen_x 
                                           && s.get_y() > 0 && s.get_y() < screen_y; 
                                     };

for (auto & player : players)
    std::copy_if(ships.begin(), ships.end(), 
                 std::back_inserter(player.visible),
                 is_visible);
std::vector<Ship> visible;

std::copy_if(ships.begin(), ships.end(), 
             std::back_inserter(visible),
             [=](Ship const &s) { return s.get_x() > 0 && s.get_x() < screen_x 
                                      && s.get_y() > 0 && s.get_y() < screen_y; });

for (auto &player : players)
    player.visible = visible;