我有第三方库,该库返回由strdup(分别为wcsdup函数)在其中创建的char *(和wchar_t *)。
我想避免在代码末尾手动调用free。
是否可以为std :: basic_string编写分配器,以便处理该库返回的C字符串?理想情况下,我根本不想分配任何新内存,而是使用返回的内存块(字符串应该是常量)。
答案 0 :(得分:8)
可悲的是,std :: string进行自己的内存管理,并且无法重用已分配的字符串。
您可以将它们复制到std :: string并立即将其删除,但这将调用您试图避免的所有行为。
您可以做的就是立即使用自定义删除器声明一个unique_ptr。如果超出范围,它将调用删除器,即free()
。同时,您可以像使用原始指针一样使用它。
std::unique_ptr<char, decltype(free)*> RAII(makeAPICall(), free);
将来,您可以为std :: string_view创建一个拥有的包装,在短期内滚动自己的包装可能会有好处,但是除非您拥有更新了所有功能的较新的stdlib(c ++ 17)采取string_view的方法我认为这是徒劳的。
答案 1 :(得分:4)
您不能使用_t()
。 std::basic_string
管理它自己的内存,因此它将分配新的存储并将数据复制到字符串中。您仍然必须手动从返回的指针释放存储。
如果可以使用C ++ 17,则可以使用std::basic_string
,因为它将仅保存指针的副本,但是您遇到了同样的问题,您需要手动调用该函数的释放函数。指针完成后。
您可以做的是将std::basic_string_view
或std::unique_ptr
与自定义删除器一起使用,以存储从函数返回的指针,这样它将自动为您重新分配内存。然后,如果您可以使用C ++ 17,则可以获取指向该指针的std::shared_ptr
,以便无需复制就可以使用所有字符串函数。否则,可以使用std::basic_string_view
中的c字符串函数来使用它或编写自己的<cstring>
版本(或找到具有类似this one的C ++ 11库)
答案 2 :(得分:2)
我想避免在代码末尾手动调用free。
如果该库没有这样做,那么您将无法避免调用free
(不管是否有意泄漏内存)。
如果库本身不使用字符串,那么如果您想使用std::string
和std::wstring
,则可以使用接受CharT*
的构造函数,并在创建后立即使用字符串,使用free
释放原始字符串。
如果您希望避免其他分配和复制,那么std::string
是不可行的。当指针超出范围时,可以使用智能指针进行释放。
答案 3 :(得分:2)
在c++17中有string_view
。
template<class T, class Deleter=std::default_delete<T>>
struct string_view_buff : std::string_view<T> {
std::unique_ptr<T[]> buff;
explicit string_view_buff( T* in, Deleter d = {} ):
buff( in, std::move(d) ),
std::string_view<T>(in) {}
};
类似的东西可以获取缓冲区的所有权,并同时公开类似字符串的功能,而无需额外的堆分配。 (代码未经测试)
在此之前,否,std::string
分配和管理自己的内存。您不能为其提供缓冲区和删除功能。