std :: map使用Vector3键VERSUS std :: vector使用复合索引

时间:2013-09-17 15:42:46

标签: c++ c++11 stdvector stdmap

我正在创建一个tilemap,并试图决定如何存储和引用每个tile。我当前的两个选项是:

  1. 一个std :: vector,其中我使用复合x,y,z calc作为键;
  2. 或者使用Vector3i作为键的std :: map。
  3. 我的问题是:基于易用性和/或性能,我应该倾向于/倾向于哪种方法。我想不同方法之间的内存/大小/存储也可以作出决定。批评是受欢迎的,因为在我的引擎基于此之前我想要一些意见。

    以下是使用复合矢量的示例:

    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    unsigned int mapWidth = 10, mapHeight = 10, mapDepth = 2;
    
    struct Vector3i {
        Vector3i() {};
        Vector3i(unsigned int x, unsigned int y, unsigned int z) : x(x), y(y), z(z) {}
        unsigned int x, y, z;
    };
    
    struct Tile {
        Tile() {};
        std::vector<unsigned int> children;
        bool visible;
        Vector3i coord;
    };
    
    unsigned int getIndex(unsigned int x, unsigned int y, unsigned int z) {
        return (y*mapWidth) + x + (z * (mapWidth * mapHeight));
    }
    
    int main() {
    
        std::vector<Tile> tiles;
        tiles.resize(mapWidth * mapHeight * mapDepth);
    
        for( int x = 0; x < mapWidth; x++ ) {
            for( int y = 0; y < mapHeight; y++ ) {
                for( int z = 0; z < mapDepth; z++) {
                    unsigned int idx = getIndex(x,y,z);
                    tiles[idx].coord = Vector3i(x,y,z);
                    tiles[idx].visible = true;
                    tiles[idx].children.push_back(1);
                }
            }
        }
    
        std::for_each(tiles.begin(), tiles.end(), [&] (const Tile& tile) {
            std::cout << tile.coord.x << "," << tile.coord.y << "," << tile.coord.z << std::endl;
        });
    
        const Tile& myTile = tiles[getIndex(1,1,1)];
        std::cout << '\n' << myTile.coord.x << "," << myTile.coord.y << "," << myTile.coord.z << std::endl;
    
        return 0;
    };
    

    以下是使用std :: map方法的示例:

    #include <vector>
    #include <map>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    struct Vector3i {
        Vector3i() {};
        Vector3i(unsigned int x, unsigned int y, unsigned int z) : x(x), y(y), z(z) {}
        unsigned int x, y, z;
    };
    
    struct Tile {
        std::vector<unsigned int> children;
        bool visible;
        Vector3i coord;
    };
    
    class comparator {
        public:
            bool operator()(const Vector3i& lhs, const Vector3i& rhs) const {
                return lhs.x < rhs.x
                    || ( lhs.x == rhs.x && ( lhs.y < rhs.y
                    || ( lhs.y == rhs.y && lhs.z < rhs.z)));
            }
    };
    
    int main() {
        unsigned int mapWidth = 5, mapHeight = 5, mapDepth = 2;
        std::map<Vector3i, Tile, comparator> tiles;
    
        for( int x = 0; x < mapWidth; x++ ) {
            for( int y = 0; y < mapHeight; y++ ) {
                for( int z = 0; z < mapDepth; z++) {
                    Vector3i key(z,y,x);
    
                    Tile tile;
                    tile.coord = Vector3i(x,y,z);
                    tile.visible = true;
                    tile.children.push_back(1);
    
                    tiles.insert(std::make_pair<Vector3i, Tile>(key, tile));
                }
            }
        }
    
        for( std::map<Vector3i, Tile, comparator>::iterator iter = tiles.begin(); iter != tiles.end(); ++iter ) {
            std::cout << iter->second.coord.x << "," << iter->second.coord.y << "," << iter->second.coord.z << std::endl;
        }
    
        auto found = tiles.find(Vector3i(1,1,1));
        const Tile& myTile = found->second;
        std::cout << '\n' << myTile.coord.x << "," << myTile.coord.y << "," << myTile.coord.z << std::endl;
    
        return 0;
    };
    

    好的,谢谢你!

1 个答案:

答案 0 :(得分:1)

使用单个向量存储整个tilemap将要求整个tilemap位于连续的内存块中。根据tilemap的大小,这可能是也可能不是问题(使用您当前的大小,它不会,但如果它被扩展到更大的3D空间,它可能很容易变得太大而无法分配在一个连续的区块中。)

如果您需要以某种有序的方式遍历3D空间,地图将不是您最好的容器(因为项目不一定按您想要的逻辑顺序显示)。

另一种可能的解决方案是使用矢量向量到瓦片的向量,这样可以方便地迭代3​​D空间,同时也不需要大量连续的数据块(只需要一行一行的瓦片就需要连续的)。