Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.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++ 标准::地图<&燃气轮机;或std::vector<&燃气轮机;当处理大量的旗帜时?_C++_Vector_Map - Fatal编程技术网

C++ 标准::地图<&燃气轮机;或std::vector<&燃气轮机;当处理大量的旗帜时?

C++ 标准::地图<&燃气轮机;或std::vector<&燃气轮机;当处理大量的旗帜时?,c++,vector,map,C++,Vector,Map,我正在编写一个编译器,有一大组标志。在大多数情况下,我的节点将接收非常少的标志(最大的大约12个),但标志的总数相当大(超过50个)。所有标志都是枚举中定义的整数: enum flags_t { FLAG_ONE, FLAG_TWO, FLAG_THREE, [...] MAX_FLAG }; 我认为使用std::map更有意义,因为我的大多数节点都可能使用0、1或2个标志,并且节点的数量非常大(很容易变成千分之一) 但我想知道std::vector是否

我正在编写一个编译器,有一大组标志。在大多数情况下,我的节点将接收非常少的标志(最大的大约12个),但标志的总数相当大(超过50个)。所有标志都是枚举中定义的整数:

enum flags_t
{
    FLAG_ONE,
    FLAG_TWO,
    FLAG_THREE,
    [...]
    MAX_FLAG
};
我认为使用
std::map
更有意义,因为我的大多数节点都可能使用0、1或2个标志,并且节点的数量非常大(很容易变成千分之一)

但我想知道
std::vector
是否真的会更有效?虽然乍一看这看起来不错:

bool node::get_flag(flags_t const f)
{
    return f_flags[f];
}

void node::set_flag(flags_t const f, bool const value)
{
    f_flags[f] = value;
}
需要在初始化时分配向量(即大小适当),或者get_flag()函数需要测试f是否是向量的一部分:

bool node::get_flag(flags_t const f)
{
    return f >= f_flags.size() ? false : f_flags[f];
}
我在resize()调用中看到的问题是,我们会一直分配/释放内存,即使我们最终从未实际使用过向量(大多数节点不需要任何标志!),因此在执行get时测试限制可能是一个很好的折衷,但我们还需要确保set_flag()调用中的向量足够大。。。(在这种情况下,我们可能会一次分配整个标志集,以避免重新分配。)


所以。。。
std::vector
std::map
会更好吗?或者
std::set
会更好吗?(我以前没有使用过std::set…

对于标志,
std::set
std::map
都是次优选择,因为它们动态分配存储,导致不必要的碎片

表示标志的一种简单方法是将它们存储在整数类型中。未签名的64位类型将为64个标志提供空间。这将是空间效率和CPU效率,和习惯性的C++引导。例如:

enum flag_code
{
    FLAG_ONE = 1ULL << 0,
    FLAG_TWO = 1ULL << 1,
    FLAG_THREE = 1ULL << 2,
    [...]
};

typedef uint64_t flags_t;

void node::set_flag(flag_code f, bool value)
{
    if (value)
        f_flags |= f;
    else
        f_flags &= ~f;
}

bool node::get_flag(flag_code f)
{
    return bool(f_flags & f);
}

std::set
std::map
都是次优的标志选择,因为它们动态分配存储,导致不必要的碎片

表示标志的一种简单方法是将它们存储在整数类型中。未签名的64位类型将为64个标志提供空间。这将是空间效率和CPU效率,和习惯性的C++引导。例如:

enum flag_code
{
    FLAG_ONE = 1ULL << 0,
    FLAG_TWO = 1ULL << 1,
    FLAG_THREE = 1ULL << 2,
    [...]
};

typedef uint64_t flags_t;

void node::set_flag(flag_code f, bool value)
{
    if (value)
        f_flags |= f;
    else
        f_flags &= ~f;
}

bool node::get_flag(flag_code f)
{
    return bool(f_flags & f);
}

使用位的好处是可以使用逐位操作一次检查所有标志。std::vector?=>标准::bitset@smoothware嗯,他们每个布尔至少使用一个比特。我在想象一些C风格的东西。类似于第一个答案。使用位的好处是可以使用逐位操作一次检查所有标志。std::vector?=>标准::bitset@smoothware嗯,他们每个布尔至少使用一个比特。我在想象一些C风格的东西。类似于第一个答案。我有超过64位,尽管我可以对它们进行分组,而且每个组甚至没有超过16位(尽管这可能会随着时间的推移而增加),出于安全原因(即避免bug),我不希望有任何重叠。这样,如果我检查了错误的标志,我会得到一个错误,而不是一些与软件预期功能无关的随机结果。但是位集可能是最好的解决方案。@Alexiswillke您的问题指出位的总数“超过50”,这给人的印象是低于64位。我现在更新了答案。你是对的!我不知道确切的数字,但可能会超过64。我正在考虑将标志和属性(也是标志)组合在一个集合中,这意味着我将讨论64。感谢您的更新,这将帮助我,因为我以前没有使用过
std::bitset
。我有超过64位,尽管我可以对它们进行分组,每个组甚至没有超过16位(尽管这可能会随着时间的推移而增加),出于安全原因(即,为了避免bug),我不希望有任何重叠。这样,如果我检查了错误的标志,我会得到一个错误,而不是一些与软件预期功能无关的随机结果。但是位集可能是最好的解决方案。@Alexiswillke您的问题指出位的总数“超过50”,这给人的印象是低于64位。我现在更新了答案。你是对的!我不知道确切的数字,但可能会超过64。我正在考虑将标志和属性(也是标志)组合在一个集合中,这意味着我将讨论64。感谢您的更新,这将帮助我,因为我以前没有使用过
std::bitset
enum flag_code
{
    FLAG_ONE = 1ULL << 0,
    FLAG_TWO = 1ULL << 1,
    FLAG_THREE = 1ULL << 2,
    [...]
};

typedef uint64_t flags_t;

void node::set_flag(flag_code f, bool value)
{
    if (value)
        f_flags |= f;
    else
        f_flags &= ~f;
}

bool node::get_flag(flag_code f)
{
    return bool(f_flags & f);
}
enum flag_code
{
    FLAG_ONE,
    FLAG_TWO,
    FLAG_THREE,
    [...]
    MAX_FLAG
};

typedef std::bitset<MAX_FLAG - 1> flags_t;

void node::set_flag(flag_code f, bool value)
{
    f_flags[f] = value;
}

bool node::get_flag(flag_code f)
{
    return f_flags[f];
}