Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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++ 如何优化字符串复制(内存分配)?_C++_String_Visual Studio 2008_Visual C++_Stl - Fatal编程技术网

C++ 如何优化字符串复制(内存分配)?

C++ 如何优化字符串复制(内存分配)?,c++,string,visual-studio-2008,visual-c++,stl,C++,String,Visual Studio 2008,Visual C++,Stl,我正在制作一个程序(想想:类似的东西),它或多或少地通过一堆字符串,并根据一些标准对它们进行排序 我将结果存储在向量中,其中结构当前定义如下: struct SearchSuggestion { std::string path; int tag; }; 在我的程序中,由于需要操作大量的文件路径等等,我复制了大量的结构(因此也复制了字符串) 虽然这会在释放模式中造成明显但很小的延迟,但会大大降低程序的调试速度(即,在击键之间有几秒钟的暂停)。寻找原因,我发现几乎所有的时间都花在

我正在制作一个程序(想想:类似的东西),它或多或少地通过一堆字符串,并根据一些标准对它们进行排序

我将结果存储在
向量中,其中结构当前定义如下:

struct SearchSuggestion
{
    std::string path;
    int tag;
};
在我的程序中,由于需要操作大量的文件路径等等,我复制了大量的结构(因此也复制了字符串)

虽然这会在释放模式中造成明显但很小的延迟,但会大大降低程序的调试速度(即,在击键之间有几秒钟的暂停)。寻找原因,我发现几乎所有的时间都花在以下堆栈跟踪上:

ntdll.dll!RtlCompareMemoryUlong()   
ntdll.dll!RtlpAllocateHeap()    
ntdll.dll!RtlAllocateHeap()     
ntdll.dll!RtlDebugAllocateHeap()    
ntdll.dll!string "Enabling heap debug options\n"()  
ntdll.dll!RtlAllocateHeap()     
msvcr90d.dll!_heap_alloc_base(unsigned __int64)     C
msvcr90d.dll!_heap_alloc_dbg_impl(unsigned __int64, int, const char *, int, int *)
msvcr90d.dll!_nh_malloc_dbg_impl(unsigned __int64, int, int, const char *, int, int *)
msvcr90d.dll!_nh_malloc_dbg(unsigned __int64, int, int, const char *, int)
msvcr90d.dll!malloc(unsigned __int64)
msvcr90d.dll!operator new(unsigned __int64)
MyProgram.exe!std::_Allocate<wchar_t>(unsigned __int64, wchar_t *)
MyProgram.exe!std::allocator<wchar_t>::allocate(unsigned __int64)
MyProgram.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::_Copy(unsigned __int64, unsigned __int64)
MyProgram.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::_Grow(unsigned __int64, bool)
MyProgram.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::assign(const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > &, unsigned __int64, unsigned __int64)
MyProgram.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >(const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > &)
MyProgram.exe!SearchSuggestion::SearchSuggestion(const SearchSuggestion &)
MyProgram.exe!std::_Construct<SearchSuggestion,SearchSuggestion>(SearchSuggestion *, const SearchSuggestion &)
MyProgram.exe!std::allocator<SearchSuggestion>::construct(SearchSuggestion *, const SearchSuggestion &)
MyProgram.exe!std::_Uninit_copy<SearchSuggestion * __ptr64,SearchSuggestion * __ptr64,std::allocator<SearchSuggestion> >(SearchSuggestion *, SearchSuggestion *, SearchSuggestion *, std::allocator<SearchSuggestion> &, std::_Nonscalar_ptr_iterator_tag, std::_Nonscalar_ptr_iterator_tag)
MyProgram.exe!stdext::unchecked_uninitialized_copy<SearchSuggestion * __ptr64,SearchSuggestion * __ptr64,std::allocator<SearchSuggestion> >(SearchSuggestion *, SearchSuggestion *, SearchSuggestion *, std::allocator<SearchSuggestion> &)
MyProgram.exe!std::_Uninit_move<SearchSuggestion * __ptr64,SearchSuggestion * __ptr64,std::allocator<SearchSuggestion>,std::_Undefined_move_tag>(SearchSuggestion *, SearchSuggestion *, SearchSuggestion *, std::allocator<SearchSuggestion> &, std::_Undefined_move_tag, std::_Undefined_move_tag)
MyProgram.exe!stdext::_Unchecked_uninitialized_move<SearchSuggestion * __ptr64,SearchSuggestion * __ptr64,std::allocator<SearchSuggestion> >(SearchSuggestion *, SearchSuggestion *, SearchSuggestion *, std::allocator<SearchSuggestion> &)
MyProgram.exe!std::vector<SearchSuggestion,std::allocator<SearchSuggestion> >::_Umove<SearchSuggestion * __ptr64>(SearchSuggestion *, SearchSuggestion *, SearchSuggestion *)
MyProgram.exe!std::vector<SearchSuggestion,std::allocator<SearchSuggestion> >::_Insert_n(std::_Vector_const_iterator<SearchSuggestion,std::allocator<SearchSuggestion> > *, unsigned __int64, const SearchSuggestion &)
MyProgram.exe!std::vector<SearchSuggestion,std::allocator<SearchSuggestion> >::insert(std::_Vector_const_iterator<SearchSuggestion,std::allocator<SearchSuggestion> > *, const SearchSuggestion &)
MyProgram.exe!std::vector<SearchSuggestion,std::allocator<SearchSuggestion> >::push_back(const SearchSuggestion &)
MyProgram.exe!Appender<std::vector<SearchSuggestion,std::allocator<SearchSuggestion> > >(const wchar_t *, _tfinddata *, void *)
MyProgram.exe!EnumMatches(const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > &, const std::vector<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,std::allocator<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > > > &, int (const wchar_t *, _tfinddata *, void *)*, void *, int)
...
ntdll.dll!RTLComparemoryulong()
ntdll.dll!RtlpAllocateHeap()
ntdll.dll!RtlAllocateHeap()
ntdll.dll!RtlDebugAllocateHeap()
ntdll.dll!字符串“启用堆调试选项\n”()
ntdll.dll!RtlAllocateHeap()
msvcr90d.dll_堆分配基(无符号int64)C
msvcr90d.dll_heap\u alloc\u dbg\u impl(unsigned\u int64,int,const char*,int,int*)
msvcr90d.dll_nh_malloc_dbg_impl(无符号_int64,int,int,const char*,int,int*)
msvcr90d.dll_nh_malloc_dbg(无符号_int64,int,int,常量字符*,int)
msvcr90d.dll!malloc(未签名的_int64)
msvcr90d.dll!运算符新(未签名的\uuu int64)
MyProgram.exe!std::_分配(未签名的uu int64,wchar\u t*)
MyProgram.exe!std::allocator::allocate(无符号\uuu int64)
MyProgram.exe!std::basic_string::_Copy(unsigned_uuint64,unsigned_uint64)
MyProgram.exe!std::basic_string::_Grow(unsigned uu int64,bool)
MyProgram.exe!std::basic_string::assign(常量std::basic_string&,无符号uuu int64,无符号uuu int64)
MyProgram.exe!标准::基本字符串::基本字符串(常量标准::基本字符串&)
MyProgram.exe!SearchSuggestion::SearchSuggestion(const SearchSuggestion&)
MyProgram.exe!标准::_构造(SearchSuggestion*,const SearchSuggestion&)
MyProgram.exe!std::allocator::construct(SearchSuggestion*,const SearchSuggestion&)
MyProgram.exe!std:_Uninit_copy(SearchSuggestion*、SearchSuggestion*、SearchSuggestion*、std::分配器&,std:_Nonscalar\u ptr\u迭代器\u标记,std:_Nonscalar\u ptr\u迭代器\u标记)
MyProgram.exe!stdext::unchecked\u uninitialized\u copy(SearchSuggestion*、SearchSuggestion*、SearchSuggestion*、std::allocator&)
MyProgram.exe!std:_Uninit_move(SearchSuggestion*,SearchSuggestion*,SearchSuggestion*,std::分配器&,std:_未定义的_move_标记,std:_未定义的_move_标记)
MyProgram.exe!stdext::\u未选中\u未初始化\u移动(SearchSuggestion*、SearchSuggestion*、SearchSuggestion*、std::分配器&)
MyProgram.exe!std::vector::move(搜索建议*,搜索建议*,搜索建议*)
MyProgram.exe!std::vector::_Insert_n(std:_vector_const_iterator*,unsigned uu int64,const SearchSuggestion&)
MyProgram.exe!std::vector::insert(std:_vector_const_iterator*,const SearchSuggestion&)
MyProgram.exe!std::vector::push_back(const SearchSuggestion&)
MyProgram.exe!附录(常量wchar\u t*,\u tfinddata*,void*)
MyProgram.exe!EnumMatches(常量std::basic_string&,常量std::vector&,int(常量wchar_t*,_tfinddata*,void*),void*,int)
...
所以很明显,复制
std::string
花费的时间太长,可能是因为引用的局部性差

现在我的问题很简单:


如何提高分配大量小字符串的性能?最好的答案是:不要分配和复制大量字符串。改为使用指向常量字符串或符号的共享指针


Malloc()和strcpy()都很慢,周期长,复制字符串总是一个O(n)操作。在实时代码中,最好尽量避免分配。

一种方法是停止将它们按值放入
搜索建议结构中。相反,为每个
SearchSuggestion
指定一个表示路径的
std::string
句柄

struct SearchSuggestion {
  int pathId;
  int tag;
};
这将使向量内的复制更加有效,因为它只是围绕简单的
int
s而不是复杂的
std::string
值进行复制

然后可以使用
std::map
结构将路径id映射到实际路径

试试boost::flyweight:


您可以尝试使用Boost.Flyweight。我不能保证它会工作-不复制字符串节省的时间可能会花在检查该字符串是否尚未存储上-但您可以尝试一下

另一个选择是将其转换为
boost::shared\u ptr
。现在只需要复制一个指针(因此成本实际上为空),但现在实际访问该字符串时会增加成本(但这可能不是什么大问题)


尝试这两种方法,看看哪一种效果更好,应该不难。

试试VS2010。有了移动语义和小字符串优化,我很想相信它会表现得更好。@KerrekSB:2010年整个IDE的速度(加起来)比我在程序中所经历的还要慢,所以这对情况并没有什么帮助(EnumMatches()
和Appender()
到底在做什么?了解这一点可以更容易地提出避免复制字符串的建议(例如,将副本缓存到某个位置可能是可能的,也是适当的)@MichaelBurr:
Appender
只有4行——它从给定的字符串创建一个
SearchSuggestion
,并将结果推送到
向量中
EnumMatches
是程序的主要部分——它枚举一组匹配项(由给定的参数确定)并为每一个调用给定的回调。它们都执行一些字符串复制。还有一个未显示的
RankMatches
——它也执行字符串复制,并返回一对建议向量和一些其他排名数据。我确实可能可以缓存