【问题标题】:Optimize inserting std::uint32_t's into a std::vector<char>优化将 std::uint32_t 插入 std::vector<char>
【发布时间】:2023-03-07 05:28:01
【问题描述】:

我正在尝试将一个无符号整数数组插入到 std::vector 中。

这是我当前的代码:

auto add_chars(std::vector<char> & vec, unsigned val[]){
    std::string tmp;
    tmp.resize(11) // Max chars a uint can be represented by, including the '\n' for sprintf
    for (auto x = 0; x< 10; x++){
        auto char_count = sprintf(tmp.data(),"%u", val[x]);
        vec.insert(vec.begin()+vec.size(),tmp.data(), tmp.data()+char_count);
    }

}

int main(){
    std::vector<char> chars;
    unsigned val[10] {1,200,3,4,5,6000,7,8,9000};
    add_chars(chars,val);
    for (auto & item : chars){
        std::cout << item;
    }
}

这个解决方案有效,但我质疑它的效率(和优雅)。

两个问题:

  • 有没有更惯用的方法来做到这一点?
  • 有没有更有效的方法来做到这一点?

*edit 修正了转移到这里时代码中的一个错误。

另外,我知道 '9000' 不能表示为 1 个字符,这就是为什么我使用缓冲区和 sprintf 为一个 uint 生成多个字符。

【问题讨论】:

  • '这行得通'。不是真的,你正在写一个零长度的字符串。 sprintf 不会调整字符串的大小以适合您放入其中的字符。我想它只是在实践中起作用,因为 短字符串优化 的常见实现技术意味着您可以在字符串对象本身中使用一些字节。
  • 在字符向量中插入整数数组有什么意义?
  • tmp.data() 是只读的。没有?
  • 嗯,但是当您尝试将 9000 转换为字符时,您期望什么?
  • @Narase 不,这是词法转换。

标签: c++


【解决方案1】:

有没有更惯用的方法?

字符流是惯用的。不幸的是,该标准只有一个用于构建字符串的流;不是向量。您可以将字符串复制到向量中。这不是最有效的方法:

std::ostringstream ss;
unsigned val[10] {1,200,3,4,5,6000,7,8,9000};
for (auto v : val)
    ss << v;
std::string str = ss.str();

// if you need a vector for some reason
std::vector<char> chars(std::begin(str), std::end(str));

或者您可以编写自己的自定义矢量流,但这将是很多样板。

【讨论】:

  • 我喜欢这个解决方案,我并不严格需要使用向量,由于 SSO,它们对 std::move() 比字符串更快。
  • @vddox 在假设之前我会先分析一下,即使使用 SSO,大多数字符串也会移动得非常快。
【解决方案2】:

我会进行一些更改(并修复错误)。

首先整数中的位数是有限的,所以不需要使用像std::string 这样的动态对象,一个简单的字符数组就可以了。由于您使用的是 uint32_t 和十进制数字,因此 10 个字符就足够了,如果包含 nul 终止符,则为 11 个字符。

其次,sprintf 和类似的效率低下,因为它们必须解释格式字符串,在您的情况下为 "%u"。执行从uint32_t 到数字的转换的手写函数会更有效。

【讨论】:

  • 或者他们可以使用std::to_chars
  • @Mgetz 是的,不知道那个。
猜你喜欢
  • 2012-03-07
  • 2013-08-18
  • 2019-05-07
  • 2018-05-31
  • 1970-01-01
  • 2016-02-04
  • 1970-01-01
  • 2018-12-13
  • 1970-01-01
相关资源
最近更新 更多