C++ 中的 Char* 与 String Speed

2024-03-08

我有一个 C++ 程序,它将从二进制文件中读取数据,最初我将数据存储在std::vector<char*> data。我更改了代码,现在使用字符串而不是 char*,这样std::vector<std::string> data。我必须做出的一些改变是从strcmp to compare例如。

然而我发现我的执行时间急剧增加。对于示例文件,当我使用 char* 时,需要 0.38 秒,转换为字符串后,在我的 Linux 机器上需要 1.72 秒。我在我的 Windows 机器上观察到类似的问题,执行时间从 0.59 秒增加到 1.05 秒。

我相信这个功能导致速度变慢。它是转换器类的一部分,请注意用_在变量名的末尾。我显然在这里遇到了内存问题,并且陷入了 C 和 C++ 代码之间。我希望这是 C++ 代码,所以我更新了底部的代码。

我访问ids_ and names_在另一个函数中也多次出现,因此访问速度非常重要。通过使用创建map我已经能够使用更稳定的 C++ 代码实现更快的速度,而不是两个单独的向量。谢谢大家!

示例 NewList.Txt

2515    ABC 23.5    32  -99 1875.7  1  
1676    XYZ 12.5    31  -97 530.82  2  
279  FOO 45.5    31  -96  530.8  3  

旧代码:

void converter::updateNewList(){
    FILE* NewList;
    char lineBuffer[100];
    char* id = 0;
    char* name = 0;

    int l = 0;
    int n;

    NewList = fopen("NewList.txt","r");
    if (NewList == NULL){
        std::cerr << "Error in reading NewList.txt\n";
        exit(EXIT_FAILURE);
    } 

    while(!feof(NewList)){
        fgets (lineBuffer , 100 , NewList); // Read line    
        l = 0;
        while (!isspace(lineBuffer[l])){
            l = l + 1;
        }

        id = new char[l];
        switch (l){
            case 1: 
                n = sprintf (id, "%c", lineBuffer[0]);
                break;
            case 2:
                n = sprintf (id, "%c%c", lineBuffer[0], lineBuffer[1]);
                break;
            case 3:
                n = sprintf (id, "%c%c%c", lineBuffer[0], lineBuffer[1], lineBuffer[2]);        
                break;
            case 4:
                n = sprintf (id, "%c%c%c%c", lineBuffer[0], lineBuffer[1], lineBuffer[2],lineBuffer[3]);
                break;
            default:
                n = -1;
                break;
        }
        if (n < 0){
            std::cerr << "Error in processing ids from NewList.txt\n";
            exit(EXIT_FAILURE);
        }

        l = l + 1;
        int s = l;
        while (!isspace(lineBuffer[l])){
            l = l + 1;
        }
        name = new char[l-s];
        switch (l-s){
            case 2:
                n = sprintf (name, "%c%c", lineBuffer[s+0], lineBuffer[s+1]);
                break;
            case 3:
                n = sprintf (name, "%c%c%c", lineBuffer[s+0], lineBuffer[s+1], lineBuffer[s+2]);
                break;
            case 4:
                n = sprintf (name, "%c%c%c%c", lineBuffer[s+0], lineBuffer[s+1], lineBuffer[s+2],lineBuffer[s+3]);
                break;
            default:
                n = -1;
                break;
        }
        if (n < 0){
            std::cerr << "Error in processing short name from NewList.txt\n";
            exit(EXIT_FAILURE);
        }


        ids_.push_back ( std::string(id) );
        names_.push_back(std::string(name));
    }

    bool isFound = false;
    for (unsigned int i = 0; i < siteNames_.size(); i ++) {
        isFound = false;
        for (unsigned int j = 0; j < names_.size(); j ++) {
            if (siteNames_[i].compare(names_[j]) == 0){
                isFound = true;
            }
        }
    }

    fclose(NewList);
    delete [] id;
    delete [] name;
}

C++ CODE

void converter::updateNewList(){
    std::ifstream NewList ("NewList.txt");

    while(NewList.good()){
        unsigned int id (0);
        std::string name;

        // get the ID and name
        NewList >> id >> name;

        // ignore the rest of the line
        NewList.ignore( std::numeric_limits<std::streamsize>::max(), '\n');

        info_.insert(std::pair<std::string, unsigned int>(name,id));

    }

    NewList.close();
}

更新:跟进问题:比较字符串的瓶颈 https://stackoverflow.com/q/3992548/363829并感谢您提供的非常有用的帮助!以后我不会再犯这些错误了!


我猜它应该与向量 的性能相关

关于向量

A std::vector http://www.cplusplus.com/reference/stl/vector/与内部连续数组一起工作,这意味着一旦数组满了,它需要创建另一个更大的数组,并逐个复制字符串,这意味着复制构造和具有相同内容的字符串的破坏,这是适得其反的...

为了轻松确认这一点,然后使用std::vector<std::string *>并查看性能是否有差异。

如果是这种情况,您可以执行以下四件事之一:

  1. 如果您知道(或知道)向量的最终大小,请使用它的方法reserve() http://www.cplusplus.com/reference/stl/vector/reserve/在内部数组中保留足够的空间,以避免无用的重新分配。
  2. use a std::deque http://www.cplusplus.com/reference/stl/deque/,它的工作原理几乎像一个向量
  3. use a std::list http://www.cplusplus.com/reference/stl/list/(这不会让您随机访问其项目)
  4. 使用 std::vector

关于字符串

注意:我假设您的 strings\char * 创建一次,并且未修改(通过 realloc、追加等)。

如果以上想法还不够,那么......

字符串对象内部缓冲区的分配类似于a的mallocchar *,因此您应该看到两者之间几乎没有差异。

现在,如果你的char *是真实的char[SOME_CONSTANT_SIZE],那么你就避免了 malloc (因此,会比 std::string 更快)。

Edit

阅读更新后的代码后,我发现以下问题。

  1. 如果 ids_ 和 names_ 是向量,并且您对行数有丝毫了解,那么您应该使用reserve()关于ids_和nam​​es_
  2. 考虑制作ids_和nam​​es_双端队列,或列表。
  3. faaNames_ 应该是 std::map,甚至是 std::unordered_map (或者编译器上的任何 hash_map)。您当前的搜索是两个 for 循环,这是相当昂贵且低效的。
  4. 在比较字符串的内容之前,请考虑比较字符串的长度。在 C++ 中,字符串的长度(即 std::string::length())是零成本操作)
  5. 现在,我不知道你在用 isFound 变量做什么,但如果你只需要找到一个真正的相等,那么我想你应该研究算法(我不知道是否已经有一个,请参阅http://www.cplusplus.com/reference/algorithm/ http://www.cplusplus.com/reference/algorithm/),但我相信只要思考一下,这种搜索就会变得更加有效。

其他的建议:

  1. 忘记使用int用于 STL 格式的尺寸和长度。至少,使用size_t。在 64 位中,size_t 将变为 64 位,而 int 将保持 32 位,因此您的代码尚未准备好 64 位(另一方面,我看到很少有传入 8 个 Go 字符串的情况......但仍然,最好是正确的...)

Edit 2

这两种(所谓的 C 和 C++)代码是不同的。 “C 代码”要求 ids 和名称的长度小于 5,否则程序存在错误。 “C++代码”没有这样的限制。尽管如此,如果您确认名称和 id 始终少于 5 个字符,则此限制仍然是大规模优化的基础。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中的 Char* 与 String Speed 的相关文章

随机推荐

  • 在 Android 中隐藏键盘的最佳方法

    我想知道在 EditText 输入文本后隐藏键盘的最佳方法 1 setonfocuschangelistener 是否仅在按下完成按钮或焦点从一个 EditText 更改为另一个时触发此侦听器 当我使用这个方法时 我无法隐藏键盘 2 set
  • SSMS 2012 智能感知行为

    SSMS 2012 中智能感知的行为似乎已更改 因此它的行为与 Visual Studio 或 SSMS 2008 不同 以前我总是按空格键 这会插入智能感知中当前突出显示的单词 但在 SSMS 2012 中我必须按 TAB 或按向下键然后
  • 如何使用 python 传递字符串+ web url并接收响应[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在使用 Python 和谷歌翻译
  • iOS 的 BLE 外设名称不正确

    我正在编写一个 iOS 应用程序来与 BLE 设备通信 设备可以在连接之间更改名称 不能在 BLE 连接期间 但 iOS 拒绝更改设备名称 例如 当设备名称为 SadName 时 我可以连接到该设备 我断开连接 关闭应用程序等 然后将设备的
  • 检查空值并在不存在时分配另一个值的最短方法

    我拉着varchar值来自数据库并想要设置string如果它们是 我将它们分配为 null 我目前正在这样做 if string IsNullOrEmpty planRec approved by true this approved by
  • 如何在 CSS 中组合变换?

    我有一个 CSS 动画 它使用变换来相对于其当前位置移动 CSS fish animation fishanimation 4s ease in out infinite alternate keyframes fishanimation
  • Android espresso - 如何检查 Listview 底部 TextView 的值?

    在上面的附图中 它是一个带有TextView 交付报告 的ListView Its status can be Sent or Sending or Failed 我想检查 已发送 条件 这意味着断言消息已成功发送 由于这是一个对话 新消息
  • CSS 声明 - 元素类型和 ID 还是只是 ID?

    我应该如何使用 CSS 声明 这边走 div main content width 900px border 1px solid CCC margin 20px 0 20px 0 padding 40px overflow hidden 或
  • 我可以用算术运算的方式编写关系运算符吗?

    所以我有一个相当复杂的函数 template
  • 从 csv 导入时如何获取记录为 NULL 的缺失值

    我有多个大型 csv 文件 每个文件在许多地方都有缺失值 当我将 csv 文件导入 SQLite 时 我希望将缺失值记录为 NULL 因为另一个应用程序希望缺失数据由 NULL 指示 我当前的方法无法产生预期的结果 CSV 文件 test
  • 是否可以从另一个类库中的静态类获取ConnectionString?

    我已在 appsettings json 文件中添加了连接字符串 我需要访问后台操作所需的连接字符串 但为了使用连接字符串 我必须通过同一解决方案中不同项目的静态类进行访问 我无法使用ConfigurationManager Connect
  • 当 TFS 团队查询结果发生更改时发出警报

    是否可以创建一个 TFS 警报 在某个查询的结果发生更改时通知用户 Example 我有一个查询 结果找到 10 个工作项 这些工作项之一已更改 它不再满足此查询 查询结果应为 9 我想要一条通知 告诉我查询结果已更改 也指已更改的工作项
  • 将 Spark 特征向量转换为数组

    我有一个特征列 它使用 Spark 的 VectorAssembler 打包成向量向量 如下所示 data是输入 DataFrame 类型为spark sql DataFrame val featureCols Array feature
  • 保存具有 Parse.files 数组的 Javascript 对象会导致“将循环结构转换为 JSON”错误

    当我尝试上传要解析的解析文件数组时 我遇到了 parse com 不喜欢的问题 我目前有一个数组 arr 其中填充有 base64 字符串图像数据 for var i 0 i
  • 基于Spring Security的Token认证

    我正在尝试使用 spring security 为 HTTP api 启用基于令牌的身份验证 环顾四周 我看到了有关实现过滤器和处理程序的答案 例如 Spring Security 通过 token 进行身份验证 https stackov
  • Python networkx 图:不要将旧图与新图绘制在一起

    下面是我的代码 import networkx as nx for i in range 2 G nx DiGraph if i 0 G add edge A B elif i 1 G add edge A C import matplot
  • 高流量网站的标准化或非标准化

    像 stackoverflow 这样的高流量网站的数据库设计和规范化的最佳实践是什么 应该使用规范化数据库来保存记录还是使用规范化技术或两者的组合 设计一个规范化数据库作为记录保存的主数据库以减少冗余 同时维护另一个非规范化形式的数据库用于
  • 找到 PATTERN 时合并两个文本文件的行

    我正在寻找一个 awk 或 sed 解决方案来根据匹配的模式组合 2 个文件 如下所示 本例中的模式是 cat 文件 2 中的行数始终等于文件 1 中的模式匹配数 File 1 I am a cat I am a dog I am a do
  • Python 数据框中的滚动和累积标准差

    是否有矢量化操作来计算 Python DataFrame 的累积和滚动标准差 SD 例如 我想添加一个列 c 它根据 a 列计算累积 SD 即在索引 0 中 它由于 1 个数据点而显示 NaN 而在索引 1 中 它根据 2 个数据计算 SD
  • C++ 中的 Char* 与 String Speed

    我有一个 C 程序 它将从二进制文件中读取数据 最初我将数据存储在std vector