Создайте std::string из char * безопасным способом
У меня есть char* p
, который указывает на строку \0
-terminated. Как создать С++ string
из него безопасным способом?
Вот небезопасная версия:
string foo()
{
char *p = get_string();
string str( p );
free( p );
return str;
}
Очевидным решением было бы попытаться поймать - все более простые способы?
Ответы
Ответ 1
Вы можете использовать shared_ptr
из С++ 11 или Boost:
string
foo()
{
shared_ptr<char> p(get_string(), &free);
string str(p.get());
return str;
}
Это использует очень специфическую особенность shared_ptr
, недоступную в auto_ptr
или что-то еще, а именно возможность указать пользовательский делектор; в этом случае я использую free
в качестве дебетера.
Ответ 2
Могу ли я спросить вас, какое исключение вы ожидаете в своем примере?
На многих платформах (Linux, AIX) новые или malloc никогда не потерпят неудачу, и ваше приложение будет убито os, если у вас закончится нехватка памяти.
Смотрите эту ссылку: Что происходит, когда в Linux заканчивается память.
Ответ 3
Yup - разматывание на основе стека. Современный дизайн С++ имеет общее решение, но в этом случае вы можете использовать
struct Cleanup {
void* toFree;
Cleanup(void* toFree) : toFree(toFree) {}
~Cleanup() { free(toFree); }
private:
Cleanup(Cleanup&);
void operator=(Cleanup&);
};
Независимо от того, что происходит с вашим std::string, вызывается бесплатный (toFree), когда объект Cleanup выходит из области действия.
Ответ 4
Ну, p
не указывает на строку с нулевым завершением, если get_string()
возвращает NULL; что проблема здесь, так как конструкторы std::string
, которые берут указатель на строку C с 0-концами, не могут иметь дело с NULL, который является такой же строкой C с 0-концевой строкой, что и два десятка бананов.
Итак, если get_string()
- ваша собственная функция, а не библиотечная функция, то, возможно, вы должны убедиться, что она не может вернуть NULL. Вы могли бы, например, позволить ему вернуть искомый std::string
сам, поскольку он знает его собственное состояние. В противном случае я сделал бы это, используя Cleanup
from этот ответ в качестве помощника, чтобы гарантировать, что p
не может протекать (как предложил Мартин Йорк в комментарии ):
string foo()
{
const char* p = get_string();
const Cleanup cleanup(p);
const std::string str(p != NULL ? p : "");
return str;
}
Ответ 5
Мы обычно используем ScopeGuard для этих случаев:
string foo()
{
char *p = get_string();
ScopeGuard sg = MakeGuard(&free, p);
string str( p );
return str;
}