我有一个程序可以逐行读取文件中的数据。我想将该行的一些子字符串复制到地图中,如下所示:
std::map< DWORD, std::string > my_map;
DWORD index; // populated with some data
char buffer[ 1024 ]; // populated with some data
char* element_begin; // points to some location in buffer
char* element_end; // points to some location in buffer > element_begin
my_map.insert( std::make_pair( index, std::string( element_begin, element_end ) ) );
此std::map<>::insert()
操作需要很长时间(文件解析时间加倍)。有没有办法让这个更便宜的操作?
谢谢, PaulH
编辑:更具体一点,我想知道我正在进行最少数量的复制操作,以便将文件中的数据传入地图。
答案 0 :(得分:2)
你真的需要一张地图吗?就我在你的例子中看到的那样,你只想将索引存储为键值,正如我想的那样,只是为每次插入增加了一个值。您可以使用std::vector
来完成此操作,这是最快的容器。只需使用push_back
并使用at(index)
访问该值。
答案 1 :(得分:2)
你可以尝试一些事情。数据结构和字符串本身的创建都涉及到开销。
是否需要map
?您可以尝试使用std::tr1::unordered_map
,看看是否有帮助。
查找需要多快?如果您可以使用O(n)查找时间,则可以尝试std::vector
。
您是否需要存储每个子字符串的副本?你可以只存储一个指针吗?
答案 2 :(得分:2)
也许您可以尝试其他版本的字符串构造函数:
string ( const char * s, size_t n );
如果你的字符串实现没有char *
的特化,它将被强制遍历给定的范围并单独复制每个字符。在这种情况下,上面的构造函数可能更快(只是猜测)。
答案 3 :(得分:1)
稍微回答你的补充质询。尝试暂时将地图更改为字符串向量,然后将固定字符串值插入向量时计时:
vector <string> v;
string s( "foobar" );
your insert loop:
v.push_back( s );
这应该会给你一个关于速度可能性的下限。
此外,您应该开启所有优化的时间(如果您还没有这样做)。这可能会给许多标准库操作带来惊人的差异。
答案 4 :(得分:0)
你正在存储字符串,但我猜你已经读过它们并将它们添加到地图中。这将导致副本。如果你在其中存储指向字符串的指针(字符串*而不是字符串)可能会更快。
答案 5 :(得分:0)
如果您的编译器无法优化插入中的冗余副本,您可以使用括号运算符直接分配到地图中:
my_map[index].assign(element_begin, element_end)
编辑:正如Neil指出的那样,如果可以插入重复的密钥,这将没有用。
答案 6 :(得分:0)
鉴于您需要将数据放入std::map<DWORD, std::string>
然后,是的,您正在进行最少数量的复制操作以将数据导入地图。
答案 7 :(得分:0)
我相信你使用地图的大部分执行时间都是复制字符串。 std::map
喜欢拥有自己的一切副本。因此,当您插入时,std::map
会复制键和值。
很久以前,当处理器速度很慢且内存很小时,程序员会使用指向“大”数据项的指针并传递指针而不是每次都复制数据。指针是一个比字符串小得多的实体,需要较少的执行时间来复制。也许你应该在地图中存储指向字符串的指针:
#include <map>
#include <string>
#include "boost/shared_ptr.hpp"
typedef boost::shared_ptr<string> Shared_Str_Ptr;
typedef std::map< DWORD, Shared_Str_Ptr> Map_Container;
//...
Map_Container my_map;
Shared_Str_Ptr p_str(new std::string("Hello"));
my_map[5] = p_str;
shared_ptr 会为您处理内存管理,因此在删除地图或其内容时无需担心。